/*
 * @Descripttion:
 * @version: V1.0
 * @Author: ZYP  2305592180@qq.com
 * @Date: 2025-05-27 09:50:48
 * @LastEditors: ZYP
 * @LastEditTime: 2025-11-10 13:58:34
 */
// #include "led.h"
#include "mmc.h"
#include "stdio.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "zyp_log.h"
#include "zyp_usb.h"
#include "esp_task_wdt.h"
#include "esp_timer.h"
// #include "app_main.h"
#include "soc/gpio_periph.h"
#include "soc/sdmmc_periph.h"
#include "driver/sdmmc_host.h"
#include "hal/gpio_hal.h"
#include "math.h"
#include "esp_sleep.h"

#include "soc/sdmmc_struct.h"
#include "soc/sdmmc_reg.h"

const static char *TAG = "ZYP_MMC";
uint8_t errmsage = 0;
struct RequestBuffer requestbuffer = {0};
struct ResponseBuffer responsebuffer = {0};
struct RwReciveBuffer rwRecivebuffer = {0};
#if IS_ENABLE_FACTORY_MODE_PROCESS
FactoryMode_T factory_mode_t = {0};
#endif
#if IS_ENBALE_FactoryModeProcess
FactoryModeProcess_T factory_mode_process_t = {0};
#endif
sdmmc_card_t *card = NULL;
sdmmc_command_t *cmd = NULL;
Factory_mode_err_state_e factory_mode_err_state = THE_FIRST_CMD61_ERR;
unsigned int writeMultipeCount = 1;
unsigned int readMultipeCount = 1;
// sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
size_t emmc_gpio_pin_[] = {
    CONFIG_EXAMPLE_PIN_CLK,
    CONFIG_EXAMPLE_PIN_CMD,
    CONFIG_EXAMPLE_PIN_D0,
#if CONFIG_EXAMPLE_EMMC_BUS_WIDTH_8
    CONFIG_EXAMPLE_PIN_D1,
    CONFIG_EXAMPLE_PIN_D2,
    CONFIG_EXAMPLE_PIN_D3,
    CONFIG_EXAMPLE_PIN_D4,
    CONFIG_EXAMPLE_PIN_D5,
    CONFIG_EXAMPLE_PIN_D6,
    CONFIG_EXAMPLE_PIN_D7,
#endif
};
bool is_power_off = false;
// bool is_emmc_init =false;

static size_t s_slot_width[2] = {1, 1};
#ifdef SOC_SDMMC_USE_GPIO_MATRIX
static void zyp_configure_pin_gpio_matrix(uint8_t gpio_num, uint8_t gpio_matrix_sig, gpio_mode_t mode, const char *name);
#define _configure_pins_(name, slot, mode) \
    zyp_configure_pin_gpio_matrix(s_sdmmc_slot_gpio_nums[slot].name, sdmmc_slot_gpio_sig[slot].name, mode, #name)
static sdmmc_slot_io_info_t s_sdmmc_slot_gpio_nums[SOC_SDMMC_NUM_SLOTS];
#define GPIO_NUMS(slot, name) s_sdmmc_slot_gpio_nums[slot].name
#elif SOC_SDMMC_USE_IOMUX
static void configure_pin_iomux(uint8_t gpio_num);
#define configure_pins(name, slot, mode) configure_pin_iomux(sdmmc_slot_gpio_num[slot].name)
#define GPIO_NUM(slot, name) sdmmc_slot_gpio_num[slot].name
#endif

#if VERIFY_EMMC_CASE
size_t address_w[] = {0x1000, 0x2000, 0x3000};
size_t block_counts_w[] = {1, 2, 3};
size_t write_data[] = {0xAAAAAAAA, 0xBBBBBBBB, 0xCCCCCCCC};

uint taskId[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
uint number_block[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
uint lba[] = {0, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006, 0x00000007, 0x00008000, 0x00009000, 0x00010000};
uint tm_op_code[] = {0, 1, 2}; /// 1-  clear all task id   all the qsr    2- clear task id
#endif

void emmc_rst_pin_init(void)
{
    gpio_config_t io_conf = {
        .pin_bit_mask = (1ULL << EMMC_RST_GPIO),
        // .mode = GPIO_MODE_OUTPUT_OD,       // 开漏输出模式
        .mode = GPIO_MODE_OUTPUT,          // 推挽输出模式
        .pull_up_en = GPIO_PULLUP_DISABLE, // 禁用内部上拉（依赖外部上拉）
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .intr_type = GPIO_INTR_DISABLE,
    };
    gpio_config(&io_conf);

    // 默认设置为高电平（不复位状态）
    gpio_set_level(EMMC_RST_GPIO, 1);

    ESP_LOGI("EMMC_RST", "RST_n pin (GPIO%d) initialized, default state: HIGH", EMMC_RST_GPIO);
}

void emmc_hardware_reset(void)
{
    ESP_LOGI("EMMC_RST", "Starting hardware reset sequence...");
    gpio_set_level(EMMC_RST_GPIO, 0);
#if 1
    // ESP_LOGI("EMMC_RST", "RST_n pulled LOW");
    vTaskDelay(pdMS_TO_TICKS(RST_PULSE_WIDTH_MS));
    gpio_set_level(EMMC_RST_GPIO, 1);
    // ESP_LOGI("EMMC_RST", "RST_n released (HIGH)");
    for (size_t i = 0; i < 5; i++)
    {
        sdmmc_host_set_cclk_always_on(SDMMC_HOST_SLOT_0, 1);
        sdmmc_host_set_cclk_always_on(SDMMC_HOST_SLOT_1, 1);
    }
    // vTaskDelay(pdMS_TO_TICKS(10)); // 等待 10ms 确保设备复位完成
    ESP_LOGI("EMMC_RST", "Hardware reset sequence completed");
#endif
}

void EMMC_GPIO_init(size_t gpio_iomux_in)
{
    gpio_config_t io_conf;
    io_conf.pin_bit_mask = (1ULL << gpio_iomux_in);
    io_conf.mode = GPIO_MODE_INPUT_OUTPUT_OD; /// out put mode
    io_conf.pull_up_en = GPIO_PULLUP_DISABLE; // forhibit PULLUP （out put mode usually no need）
    io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    io_conf.intr_type = GPIO_INTR_DISABLE;
    gpio_config(&io_conf);
    ZYP_DEBUG_MMC(" initial GPIO%d, STATE:%d\n", gpio_iomux_in, gpio_get_level(gpio_iomux_in));
    // gpio_set_level(gpio_iomux_in, 0);
}

void EMMC_POWER_SET(size_t gpio_iomux_in, int value)
{
    gpio_set_level(gpio_iomux_in, value);
    ZYP_DEBUG(" set gpio_iomux_in:%d,value:%d\n", gpio_iomux_in, value);
}

void EMMC_POWERON(size_t gpio_iomux_in)
{
    ZYP_DEBUG("-------------emmc poweron------------\n");
    ZYP_DEBUG("defalust GPIO_NUMS %d\n", gpio_get_level(gpio_iomux_in));
    gpio_set_level(gpio_iomux_in, 1);
    ZYP_DEBUG("now  GPIO_NUMS %d\n", gpio_get_level(gpio_iomux_in));
}

void EMMC_POWEROF(size_t gpio_iomux_in)
{
    ZYP_DEBUG("-------------emmc poweroff------------\n");
    ZYP_DEBUG("defalust GPIO_NUMS %d\n", gpio_get_level(gpio_iomux_in));
    gpio_set_level(gpio_iomux_in, 0);
    ZYP_DEBUG("now  GPIO_NUMS %d\n", gpio_get_level(gpio_iomux_in));
}

#define ZYP_SDMMC_INIT_FUN_STEP(condition, function)                             \
    do                                                                           \
    {                                                                            \
        if ((condition))                                                         \
        {                                                                        \
            esp_err_t err = (function)(card);                                    \
            if (err != ESP_OK)                                                   \
            {                                                                    \
                ESP_LOGD(TAG, "%s: %s returned 0x%x", __func__, #function, err); \
                return err;                                                      \
            }                                                                    \
        }                                                                        \
    } while (0);

#define ZYP_SDMMC_CHECK_CMD(cmdresp, err, tag, format, ...) \
    do                                                      \
    {                                                       \
        if ((err = (cmdresp)) != ESP_OK)                    \
        {                                                   \
            ESP_LOGE(tag, format, ##__VA_ARGS__);           \
            return err;                                     \
        }                                                   \
    } while (0)

#define ZYP_Stirng_MMC_CHECK_CMD(cmdresp, err, tag, format) \
    do                                                      \
    {                                                       \
        if ((err = (cmdresp)) != ESP_OK)                    \
        {                                                   \
            ESP_LOGE(tag, "%s", (format));                  \
            return err;                                     \
        }                                                   \
    } while (0)

FactoryMode_T zyp_construct_vriginal_message_fream(FactoryMode_T factory_mode_t)
{
    ZYP_DEBUG_USB("zyp_construct_vriginal_message_fream\n");
    factory_mode_t.factory_mode_starbit = FACTORY_MODE_FREAM_START_BIT;
    factory_mode_t.factory_mode_endbit = FACTORY_MODE_FREAM_END_BIT;
    factory_mode_t.factory_mode_err_message_flage = errmsage;
    return factory_mode_t;
}

#if IS_ENBALE_FactoryModeProcess
FactoryModeProcess_T *zyp_construct_vriginal_process_message_fream(FactoryModeProcess_T *factory_mode_process_t, Factory_mode_process_state_e process_state)
{
    ZYP_DEBUG_USB("zyp_construct_vriginal_process_message_fream\n");
    factory_mode_process_t->factoryModeProcessStarbit = FACTORY_MODE_Process_FREAM_START_BIT;
    factory_mode_process_t->factoryModeProcessData = process_state;
    factory_mode_process_t->factoryModeProcessEndbit = FACTORY_MODE_Process_FREAM_END_BIT;
    return factory_mode_process_t;
}
#endif

void zyp_getrequetCmdID(struct RequestBuffer *requestbuffer, sdmmc_command_t *cmd)
{
    switch (requestbuffer->cmdId)
    {
    case 0x00:
        cmd->opcode = 0;
        break;
    case 0x01:
        cmd->opcode = 1;
        break;
    case 0x02:
        cmd->opcode = 2;
        break;
    case 0x03:
        cmd->opcode = 3;
        break;
    case 0x04:
        cmd->opcode = 4;
        break;
    case 0x05:
        cmd->opcode = 5;
        break;
    case 0x06:
        cmd->opcode = 6;
        break;
    case 0x07:
        cmd->opcode = 7;
        break;
    case 0x08:
        cmd->opcode = 8;
        break;
    case 0x09:
        cmd->opcode = 9;
        break;

    case 0x0A:
        cmd->opcode = 10;
        break;
    case 0x0B:
        cmd->opcode = 11;
        break;
    case 0x0c:
        cmd->opcode = 12;
        break;
    case 0x0d:
        cmd->opcode = 13;
        break;
    case 0x0e:
        cmd->opcode = 14;
        break;
    case 0x0f:
        cmd->opcode = 15;
        break;
    case 0x10:
        cmd->opcode = 16;
        break;
    case 0x11:
        cmd->opcode = 17;
        break;
    case 0x12:
        cmd->opcode = 18;
        break;
    case 0x13:
        cmd->opcode = 19;
        break;
    case 0x14:
        cmd->opcode = 20;
        break;
    case 0x15:
        cmd->opcode = 21;
        break;
    case 0x16:
        cmd->opcode = 22;
        break;
    case 0x17:
        cmd->opcode = 23;
        break;
    case 0x18:
        cmd->opcode = 24;
        break;
    case 0x19:
        cmd->opcode = 25;
        break;
    case 0x1a:
        cmd->opcode = 26;
        break;
    case 0x1b:
        cmd->opcode = 27;
        break;

    case 0x1C:
        cmd->opcode = 28;
        break;
    case 0x1D:
        cmd->opcode = 29;
        break;
    case 0x1E:
        cmd->opcode = 30;
        break;
    case 0x1F:
        cmd->opcode = 31;
        break;

    case 0x23:
        cmd->opcode = 35;
        break;
    case 0x24:
        cmd->opcode = 36;
        break;
    case 0X25:
        cmd->opcode = 37;
        break;
    case 0x3d:
        cmd->opcode = 61;
        break;
    case 0x3c:
        cmd->opcode = 60;
        break;
    case 0x38:
        cmd->opcode = 56;
        break;
    default:
        ZYP_DEBUG_MMC("cmdId is err\n");
        break;
    }
}

void zyp_getrespType(struct RequestBuffer *requestbuffer, sdmmc_command_t *cmd)
{

    if (requestbuffer->respType == 0 && cmd->opcode == MMC_GO_IDLE_STATE)
    {
        ZYP_DEBUG_MMC("CMD0  getrespType\n");
        cmd->flags = SCF_CMD_BCR | SCF_RSP_R3;
        card->is_mmc = 1;
        return;
    }

    else if (requestbuffer->respType == 3 && cmd->opcode == MMC_SEND_OP_COND)
    {
        ZYP_DEBUG_MMC("CMD1  getrespType\n");
        cmd->flags = SCF_CMD_BCR | SCF_RSP_R3;
        return;
    }
    else if (requestbuffer->respType == 2 && cmd->opcode == MMC_ALL_SEND_CID)
    {
        ZYP_DEBUG_MMC("CMD2 getrespType\n");
        cmd->flags = SCF_CMD_BCR | SCF_RSP_R2;
        return;
    }
    else if (requestbuffer->respType == 1 && cmd->opcode == MMC_SET_RELATIVE_ADDR)
    {
        ZYP_DEBUG_MMC("CMD3  getrespType\n");
        cmd->flags = SCF_CMD_BCR | SCF_RSP_R6;
        return;
    }
    switch (requestbuffer->respType)
    {
    case 0:
        cmd->flags = SCF_CMD_AC | SCF_RSP_R0;
        break;
    case 1:
        cmd->flags = SCF_CMD_AC | SCF_RSP_R1;
        break;
    case 2:
        cmd->flags = SCF_CMD_AC | SCF_RSP_R2;
        break;
    case 3:
        cmd->flags = SCF_CMD_AC | SCF_RSP_R3;
        break;
    case 4:
        cmd->flags = SCF_CMD_AC | SCF_RSP_R4;
        break;
    case 5:
        cmd->flags = SCF_CMD_AC | SCF_RSP_R5;
        break;
    case 6:
        cmd->flags = SCF_CMD_AC | SCF_RSP_R1B;
        break;
    default:
        ZYP_DEBUG_MMC("you transfer cmd->resp_type is err\n");
        break;
    }
}

#if IS_ENBALE_FactoryModeProcess

/// send process ZYP_DEBUG_MMC
void zyp_construct_vriginal_process_debugmessage_fream(uint8_t cmd, unsigned int args)
{
    ZYP_DEBUG_USB("zyp_construct_vriginal_process_debugmessage_fream\n");
    uint8_t data[16];

    sprintf((char *)data, "CMD%02d %08X", cmd, args);

    ZYP_DEBUG_USB("data: ");
    for (int i = 0; i < sizeof(data); i++)
    {
        ZYP_DEBUG_USB("%c ", data[i]);
    }
    ZYP_DEBUG_USB("\n");

    zyp_finall_tinyusb_cdcacm_write_queue(0, data, sizeof(data));
}

///  send process data
void zyp_construct_vriginal_process_message_fream_to_send(FactoryModeProcess_T *factory_mode_process_t, Factory_mode_process_state_e process_state, uint8_t cmd, unsigned int args)
{
    ZYP_DEBUG_USB("zyp_construct_vriginal_process_message_fream_to_send\n");
    uint8_t *processData = (uint8_t *)(zyp_construct_vriginal_process_message_fream(factory_mode_process_t, process_state));
    for (size_t i = 0; i < sizeof(FactoryModeProcess_T); i++)
    {
        ZYP_DEBUG_MMC("%02X ", processData[i]);
    }
    ZYP_DEBUG_MMC("\n");
    zyp_finall_tinyusb_cdcacm_write_queue(0, (uint8_t *)(zyp_construct_vriginal_process_message_fream(factory_mode_process_t, process_state)), FACTORY_MODE_Process_FREAM_SIZE);
    vTaskDelay(pdMS_TO_TICKS(70));
    zyp_construct_vriginal_process_debugmessage_fream(cmd, args);
}
#endif

/// @brief  0 1 2 4 6 7 9 10 12 13 15     16 55 35 36 38 60 61
/// @param
/// @return
esp_err_t zyp_judge_is_nomal_cmd(sdmmc_command_t *cmd)
{
    if (cmd->opcode == MMC_GO_IDLE_STATE || cmd->opcode == MMC_SEND_OP_COND || cmd->opcode == MMC_ALL_SEND_CID || cmd->opcode == MMC_SET_DSR || cmd->opcode == MMC_SLEEP_AWAK || cmd->opcode == MMC_SLEEP_AWAK || cmd->opcode == MMC_SWITCH || cmd->opcode == MMC_SELECT_CARD || cmd->opcode == MMC_SEND_CID || cmd->opcode == MMC_STOP_TRANSMISSION || cmd->opcode == MMC_SEND_STATUS || cmd->opcode == MMC_GO_INCTIVE || cmd->opcode == MMC_SET_BLOCKLEN || cmd->opcode == MMC_APP_CMD || cmd->opcode == MMC_ERASE_GROUP_START || cmd->opcode == MMC_ERASE_GROUP_END || cmd->opcode == MMC_ERASE || cmd->opcode == MMC_APP_CMD60 || cmd->opcode == MMC_APP_CMD61)
    {
        return MMC_TRUE;
    }
    else
    {
        return MMC_FALSE;
    }
}

esp_err_t zyp_sendNomalCmd(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer)
{
    cmd->arg = requestbuffer->cmdParm;
    cmd->data = NULL; /// must be null  if not  cmd send err why not vrigin flow is ok?
    // cmd->flags = SCF_RSP_R1B | SCF_CMD_AC | SCF_WAIT_BUSY;    just cmd6
#if IS_ENABLE_MMC_FUNCTION_DEBUG
    ZYP_DEBUG_MMC("cmd->opcode:%lx,cmd->arg:%lx,cmd->flags:%x\n", cmd->opcode, cmd->arg, cmd->flags);
#endif
    return sdmmc_send_cmd(card, cmd);
}

void zyp_wrappeRespnceDataFrameAndSendHex_nostruct(struct RequestBuffer *requestbuffer, char *sendReadDataCmdbuffer, unsigned int sendReadDataCmdbufferSize)
{
    if (requestbuffer->cmdId == MMC_CMD_BUS_TEST_R)
    {
        vTaskDelay(pdMS_TO_TICKS(500)); ///  qt bug cmd resp and data resp send totally  now separate
    }

    int i = 0;
    ZYP_DEBUG_MMC("recive buffer size:%d\n", sendReadDataCmdbufferSize);
    ZYP_DEBUG_MMC("orignal recive data:\n");
    for (i = 0; i < sendReadDataCmdbufferSize; i++)
    {
        ZYP_DEBUG_MMC("%02X,", sendReadDataCmdbuffer[i]); // should be all AA OR FF
    }

    ZYP_DEBUG_MMC("\n\n");

    ZYP_DEBUG_MMC("nosteuct 000\n");
    int rwReqequtBufferSize = 8 + sendReadDataCmdbufferSize;
    // char my_buffer[rwReqequtBufferSize]={0};                    ///: variable-sized object may not be initialized
    char *my_buffer = (char *)malloc(rwReqequtBufferSize); // Dynamic memory allocation
    if (my_buffer == NULL)
    {
        ZYP_DEBUG_MMC("Failed to allocate memory"); // Or handle the error as needed
    }

    memset(my_buffer, 0, rwReqequtBufferSize);

    my_buffer[0] = MMC_DATA_CMD_FREAM_START_BYTE;
    my_buffer[1] = MMC_DATA_CMD_FREAM_TANSFER_SLAVE_TO_HOST_FLAG;
    // my_buffer[2] = requestbuffer->rwFlag; /// 02                        todo????
    my_buffer[2] = MMC_DATA_CMD_FREAM_RFLAGE;
    my_buffer[3] = sendReadDataCmdbufferSize / EXT_CSD_MMC_SIZE;
    if (requestbuffer->cmdId == MMC_CMD_BUS_TEST_R)
    {
        my_buffer[2] = MMC_CMD_BUS_TEST_FLAG;
        my_buffer[3] = 0X08;
    }
    my_buffer[rwReqequtBufferSize - 4] = MMC_DATA_CMD_FREAM_ENDMARK_ONEBYTE;
    my_buffer[rwReqequtBufferSize - 3] = MMC_DATA_CMD_FREAM_ENDMARK_TWOBYTE;
    my_buffer[rwReqequtBufferSize - 2] = MMC_DATA_CMD_FREAM_ENDMARK_THREEBYTE;
    my_buffer[rwReqequtBufferSize - 1] = MMC_DATA_CMD_FREAM_ENDMARK_FOURBYTE; /// end bit
    memcpy(my_buffer + 4, sendReadDataCmdbuffer, sendReadDataCmdbufferSize);  /// copy data

    for (i = 0; i < rwReqequtBufferSize; i++)
    {
        ZYP_DEBUG_MMC("%02X,", my_buffer[i]);
    }
    ZYP_DEBUG_MMC("\n\n\n");
    zyp_tinyusb_cdcacm_write_queue(0, (uint8_t *)my_buffer, rwReqequtBufferSize);
    ZYP_DEBUG_MMC("\n\n\n");
    free(my_buffer);
}

void zyp_wrappeRespnceCmdFrameAndSendHex(sdmmc_command_t *cmd, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer)
{
    int responcebuffersize = sizeof(struct ResponseBuffer); /// 5+16+4
    responsebuffer->startBit = requestbuffer->startBit;
    responsebuffer->requestDirection = MMC_DATA_CMD_FREAM_TANSFER_SLAVE_TO_HOST_FLAG;
    responsebuffer->cmdId = requestbuffer->cmdId;
    responsebuffer->rwFlag = requestbuffer->rwFlag;
    responsebuffer->respType = requestbuffer->respType;
    responsebuffer->endBit = MMC_CMD_RESPONCE_FREAM_ENDBIT;

    if (requestbuffer->respType == MMC_RESPONCE_TYPE_R2)
    {
        size_t size__t = sizeof(unsigned int);
        uint8_t reversed_response[MMC_RESPONCE_BYTE];
        for (int i = 0; i < size__t; i++)
        {
            uint32_t word = cmd->response[size__t - 1 - i];
            for (int j = 0; j < size__t; j++)
            {
                reversed_response[i * size__t + j] = (word >> (j * 8)) & 0xFF;
            }
        }
        memcpy(responsebuffer->responseParm, reversed_response, sizeof(sdmmc_response_t));
    }

    else
    {
        memcpy(responsebuffer->responseParm, cmd->response, sizeof(cmd->response));
    }

#if IS_ENABLE_MMC_FUNCTION_DEBUG
    ZYP_DEBUG_MMC("sizeof(responsebuffer):%d\n", responcebuffersize);
    ZYP_DEBUG_MMC("cmd responsebuffer is:\n");
    char *hex_str = (char *)responsebuffer;
    for (int i = 0; i < responcebuffersize; i++)
    {
        /// printf respon data frame
        ZYP_DEBUG_MMC("%02X,", hex_str[i]);
    }

    ZYP_DEBUG_MMC("\n");
    ZYP_DEBUG_MMC("resp cmd send hex to host computer\n");
#endif
    zyp_tinyusb_cdcacm_write_queue(0, (uint8_t *)hex_str, responcebuffersize);
}

void zyp_wrappeRespnceCmdR_W_Err_FrameAndSendHex(sdmmc_command_t *cmd, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer)
{

    int responsebufferSize = sizeof(struct ResponseBuffer); /// 6+16
    char *bufferarr = (char *)malloc(responsebufferSize);
    memset(bufferarr, MMC_CMD_FREAM_ERR_RESP_VALUE, MMC_CMD_FREAM_ERR_RESP_VALUE_SIZE);

    responsebuffer->startBit = requestbuffer->startBit; ///
    responsebuffer->requestDirection = MMC_DATA_CMD_FREAM_TANSFER_SLAVE_TO_HOST_FLAG;
    responsebuffer->cmdId = requestbuffer->cmdId; //
    responsebuffer->rwFlag = requestbuffer->rwFlag;
    responsebuffer->respType = requestbuffer->respType;
    responsebuffer->endBit = MMC_CMD_RESPONCE_FREAM_ENDBIT;
    memcpy(responsebuffer->responseParm, bufferarr, MMC_CMD_FREAM_ERR_RESP_VALUE_SIZE);
#if IS_ENABLE_MMC_FUNCTION_DEBUG
    ZYP_DEBUG_MMC("sizeof(responsebuffer):%d\n", responsebufferSize); // 16+6
    ZYP_DEBUG_MMC("cmd responsebuffer is:\n");
    char *hex_str = (char *)responsebuffer;
    for (int i = 0; i < responsebufferSize; i++)
    {
        ZYP_DEBUG_MMC("%02X,", hex_str[i]);
        if (i == responsebufferSize - 1)
        {
            ZYP_DEBUG_MMC("\n");
        }
    }
#endif
    zyp_tinyusb_cdcacm_write_queue(0, (uint8_t *)hex_str, responsebufferSize);
    if (bufferarr != NULL)
    {
        free(bufferarr);
        bufferarr = NULL;
    }
}

void zyp_wrappeRespnceCmd14Resp(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer, char *mybuffer)
{
    int j;
    int responsebufferSize = sizeof(struct ResponseBuffer); /// 5+16+4
    responsebuffer->startBit = requestbuffer->startBit;
    responsebuffer->requestDirection = MMC_DATA_CMD_FREAM_TANSFER_SLAVE_TO_HOST_FLAG;
    responsebuffer->cmdId = requestbuffer->cmdId;
    responsebuffer->rwFlag = requestbuffer->rwFlag;
    responsebuffer->respType = requestbuffer->respType;
    responsebuffer->endBit = MMC_CMD_RESPONCE_FREAM_ENDBIT;
    memcpy(responsebuffer->responseParm, cmd->response, sizeof(cmd->response));
    uint8_t pattern_8bit[8] = {0x55, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    uint8_t pattern_4bit[4] = {0x5a, 0, 0, 0};

    if ((card->log_bus_width) == LOG_BUS_WITH_8BIT)
    {
        for (j = 0; j < BUS_WITH_8BIT; j++)
        {
            ZYP_DEBUG_MMC("%02X ", mybuffer[j]);
            if (j == BUS_WITH_8BIT - 1)
            {
                ZYP_DEBUG_MMC("\n");
            }
        }
        if (memcmp(mybuffer, pattern_8bit, BUS_WITH_8BIT) == 0)
        {
            ZYP_DEBUG_MMC("supprort 8 bit bus test\n");
            memcpy(responsebuffer->responseParm, cmd->response, 16);
        }
        else
        {
            ZYP_DEBUG_MMC("not supprort 8 bit bus test\n");
            memset(responsebuffer->responseParm, 0XFF, 16);
        }
    }
    else if ((card->log_bus_width) == LOG_BUS_WITH_4BIT)
    {
        for (j = 0; j < 4; j++)
        {
            ZYP_DEBUG_MMC("%02X ", mybuffer[j]);
            if (j == 4 - 1)
            {
                ZYP_DEBUG_MMC("\n");
            }
        }

        if (memcmp(mybuffer, pattern_4bit, BUS_WITH_4BIT) == 0)
        {
            ZYP_DEBUG_MMC("supprort 4 bit bus test\n");
            memcpy(responsebuffer->responseParm, cmd->response, 16);
        }
        else
        {
            ZYP_DEBUG_MMC("not supprort 4 bit bus test\n");
            memset(responsebuffer->responseParm, 0XFF, 16);
        }
    }
    ZYP_DEBUG_MMC("cmd responsebuffer is:\n");
    char *hex_str = (char *)responsebuffer;
    for (j = 0; j < responsebufferSize; j++)
    {
        /// printf respon data frame
        ZYP_DEBUG_MMC("%02X,", hex_str[j]);
    }
    zyp_tinyusb_cdcacm_write_queue(0, (uint8_t *)hex_str, responsebufferSize);
}

int zyp_setBlockCountCmd(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer)
{
    int err;
    int j;
    cmd->arg = requestbuffer->cmdParm; // no think about packger 40 00 00 01  40 consider as packger
    cmd->data = NULL;                  /// if not assert err  assert(cmd->datalen % cmd->blklen == 0);
    ZYP_DEBUG_MMC("cmd23_parm::%d\n", (unsigned int)cmd->arg);
#if 0
    if (sdmmc_send_cmd(card, cmd))
    {
        ZYP_DEBUG_MMC("zyp_setBlockCountCmd ERR\n");
    }
#endif
    ZYP_DEBUG_MMC("zyp_setBlockCountCmd count: %d\n", (unsigned int)cmd->arg);
    ZYP_DEBUG_MMC("send cmd emmc resp: \n");
    for (j = 0; j < 16; j++)
    {
        ZYP_DEBUG_MMC("cmd->response[%d]:%08X\n ", j, (size_t)cmd->response[j]);
    }
    ZYP_DEBUG_MMC("\n");
    return (int)cmd->arg;
}

esp_err_t zyp_process_protect_command(struct RwReciveBuffer *rwRecivebuffer, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer)
{
    sdmmc_command_t cmd_protect = {
        .blklen = rwRecivebuffer->dataLength,
        .arg = requestbuffer->cmdParm,
        .data = rwRecivebuffer->data,
        .datalen = rwRecivebuffer->dataLength,
        .flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_WAIT_BUSY,
        .opcode = requestbuffer->cmdId,
        .timeout_ms = SDMMC_WRITE_CMD_TIMEOUT_MS,
    };
    if (!zyp_mmc_write_sectors(&cmd_protect, card, requestbuffer, rwRecivebuffer->data, 0, 1))
    {
        zyp_handle_mmc_cmd_response(&cmd_protect, requestbuffer, responsebuffer, false);
    }
    else
    {
        zyp_handle_mmc_cmd_response(&cmd_protect, requestbuffer, responsebuffer, true);
    }
    return ESP_OK;
}

esp_err_t zyp_mmc_send_cmd_send_status(sdmmc_card_t *card, sdmmc_command_t *cmd, uint32_t *out_status)
{
    memset(cmd, 0, sizeof(sdmmc_command_t));
    cmd->opcode = MMC_SEND_STATUS;
    cmd->arg = MMC_ARG_RCA(card->rca);
    cmd->flags = SCF_CMD_AC | SCF_RSP_R1;
    esp_err_t err = sdmmc_send_cmd(card, cmd);
    if (err != ESP_OK)
    {
        return err;
    }
    if (out_status)
    {
        if (host_is_spi(card))
        {
            *out_status = SD_SPI_R2(cmd->response);
        }
        else
        {
            *out_status = MMC_R1(cmd->response);
        }
    }
    return ESP_OK;
}

/// @brief  retrun read responce not cmd13 resp to host
/// @param card
/// @param dst
/// @param start_block
/// @param block_count
/// @return

#if IS_SURE_MMC_READ_FUNCTION
esp_err_t zyp_sdmmc_read_sectors_dma(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, void *dst,
                                     size_t start_block, size_t block_count)
{
    ZYP_DEBUG_VERIFY_CASE("cmdid%d,parm:%d,solt:%d,cmd->datalen:%d,cmd_blocklen:%d\n", (size_t)cmd->opcode, (size_t)cmd->arg, card->host.slot, cmd->datalen, cmd->blklen);
#if IS_ENABLE_SEND_CMD_CSD
    if (start_block + block_count > card->csd.capacity)
    {
        return ESP_ERR_INVALID_SIZE;
    }
    size_t block_size = card->csd.sector_size; /// no hardingcode   must send cmd_csd   deflust 512 Byte
#else
    size_t block_size = EXT_CSD_MMC_SIZE;
#endif

    // if (block_count == 1)
    // {
    //     cmd->opcode = MMC_READ_BLOCK_SINGLE;
    // }
    // else
    // {
    //     cmd->opcode = MMC_READ_BLOCK_MULTIPLE;
    // }

#if 0   
    if (card->ocr & SD_OCR_SDHC_CAP)
    {
        cmd->arg = start_block;
    }
    else
    {
        cmd->arg = start_block * block_size;            /// read or write no need caculator cmd25 18 parm is address
    }
#endif
    if (requestbuffer->cmdId == MMC_READ_BLOCK_MULTIPLE && cmd->no_need_auto_stop == 1) /// PD R or cmd23 add cmd18
    {
        ZYP_DEBUG_VERIFY_CASE("%d\n", __LINE__);
        if (requestbuffer->requestDirection == 0x01) /// define end cmd23
        {
            cmd->arg = requestbuffer->cmdParm;
            cmd->opcode = requestbuffer->cmdId;
            cmd->flags = SCF_CMD_ADTC | SCF_CMD_READ | SCF_RSP_R1;
            cmd->blklen = block_size;
            cmd->data = (void *)dst;
            cmd->datalen = block_size * block_count;
        }
        else
        {
            ZYP_DEBUG_VERIFY_CASE("%d\n", __LINE__);
            /* code */ /// PD R    external construct
        }
    }

    // else if (cmd->opcode == MMC_CMD_APP_CMD_2)
    // {
    //     ZYP_DEBUG_VERIFY_CASE("%d\n", __LINE__);
    //     cmd->arg = requestbuffer->cmdParm;
    // }

    else if (requestbuffer->cmdId == MMC_SEND_WRITE_PROT || requestbuffer->cmdId == SEND_WRITE_PROT_TYPE)
    {
        ZYP_DEBUG_MMC("MMC_SEND_WRITE_PROT | SEND_WRITE_PROT_TYPE\n ");
        card->host.slot = 0;
        cmd->opcode = requestbuffer->cmdId;
        cmd->flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_CMD_READ;
        cmd->blklen = EXT_CSD_MMC_SIZE;
        cmd->datalen = block_count * EXT_CSD_MMC_SIZE;
        cmd->data = dst;
        cmd->timeout_ms = SDMMC_WRITE_CMD_TIMEOUT_MS;
        cmd->arg = start_block;
        cmd->no_need_auto_stop = 0;

        // if (cmd->data != NULL && cmd->datalen == 0)     /// external structure
        // {
        //     ESP_LOGE(TAG, "cmd %d: data is not NULL but datalen is 0", (size_t)cmd->opcode);
        //     // return ESP_ERR_INVALID_ARG;
        // }
        // card->host.slot=0;
        // cmd->data = dst;                         /// must be construct or is cmd->datalen == 0  why?   取地址当指针只能传递一层函数？？？？
        // cmd->datalen=block_count;          ///重新边0了
    }

    else
    {
        ZYP_DEBUG_VERIFY_CASE("%d\n", __LINE__);
        cmd->arg = requestbuffer->cmdParm;
        cmd->opcode = requestbuffer->cmdId;
        cmd->flags = SCF_CMD_ADTC | SCF_CMD_READ | SCF_RSP_R1;
        cmd->blklen = block_size;
        cmd->data = (void *)dst;
        cmd->datalen = block_size * block_count;
    }

    ZYP_DEBUG_MMC("%d\n", __LINE__);
    esp_err_t err = sdmmc_send_cmd(card, cmd);
    ZYP_DEBUG_MMC("%d\n", __LINE__);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "%s: sdmmc_send_cmd returned 0x%x", __func__, err);
        return err;
    }
    else
    {
        ZYP_DEBUG_VERIFY_CASE("send cmd %d pass: \n", (size_t)cmd->opcode);
    }
    uint32_t status = 0;
    size_t count = 0;
    int64_t yield_delay_us = 100 * 1000; // initially 100ms
                                         // int64_t yield_delay_us = 1000 * 1000; // initially 100ms
    int64_t t0 = esp_timer_get_time();
    int64_t t1 = 0;
    //// SD mode: wait for the card to become idle based on R1 status
    while (!host_is_spi(card) && !(status & MMC_R1_READY_FOR_DATA))
    {
        t1 = esp_timer_get_time();
        if (t1 - t0 > SDMMC_READY_FOR_DATA_TIMEOUT_US)
        {
            ESP_LOGE(TAG, "read sectors dma - timeout");
            return ESP_ERR_TIMEOUT;
        }
        if (t1 - t0 > yield_delay_us)
        {
            yield_delay_us *= 2;
            vTaskDelay(1);
        }
        err = sdmmc_send_cmd_send_status(card, &status);
        if (err != ESP_OK)
        {
            ESP_LOGE(TAG, "%s: sdmmc_send_cmd_send_status returned 0x%x", __func__, err);
            return err;
        }
        if (++count % 16 == 0)
        {
            ESP_LOGV(TAG, "waiting for card to become ready (%d)", count);
        }
    }
    return ESP_OK;
}

esp_err_t zyp_sdmmc_read_sectors(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, void *dst,
                                 size_t start_block, size_t block_count)
{
    esp_err_t err = ESP_OK;
    ZYP_DEBUG_MMC("start_block: %zu, block_count: %zu\n", start_block, block_count);
    if (block_count == 0)
    {
        ZYP_DEBUG_MMC("Error: block_count cannot be 0.\n");
        return ESP_ERR_INVALID_ARG;
    }
    if (cmd == NULL)
    {
        ZYP_DEBUG_MMC("Error: cmd is NULL.\n");
        return ESP_ERR_INVALID_ARG; // 参数为空，返回错误码
    }
    if (card == NULL)
    {
        ZYP_DEBUG_MMC("Error: card is NULL.\n");
        return ESP_ERR_INVALID_ARG;
    }
    if (requestbuffer == NULL)
    {
        ZYP_DEBUG_MMC("Error: requestbuffer is NULL.\n");
        return ESP_ERR_INVALID_ARG;
    }
    if (dst == NULL)
    {
        ZYP_DEBUG_MMC("Error: dst is NULL.\n");
        return ESP_ERR_INVALID_ARG;
    }
#if IS_ENABLE_SEND_CMD_CSD
    size_t block_size = card->csd.sector_size; /// todo must be send cmd9
#else
    size_t block_size = EXT_CSD_MMC_SIZE;
#endif

#if 1
    bool is_dma_capable = esp_ptr_dma_capable(dst);
    bool is_4byte_aligned = ((intptr_t)dst % 4 == 0);
    ESP_LOGI("TAG", "point addr: 0x%08" PRIxPTR, (uintptr_t)dst);
    ESP_LOGI("TAG", "at DMA range: %s", is_dma_capable ? "yes" : "no");
    ESP_LOGI("TAG", "addr is 4 byte aligned: %s", is_4byte_aligned ? "yes" : "no");
    ESP_LOGI("TAG", "actually aligned cnt: %" PRIuPTR, (uintptr_t)dst % 4);
#endif

    if (esp_ptr_dma_capable(dst) && (intptr_t)dst % 4 == 0)
    {
        err = zyp_sdmmc_read_sectors_dma(cmd, card, requestbuffer, dst, start_block, block_count);
    }
    else
    {
        void *tmp_buf = heap_caps_malloc(block_size, MALLOC_CAP_DMA);
        if (tmp_buf == NULL)
        {
            return ESP_ERR_NO_MEM;
        }
        uint8_t *cur_dst = (uint8_t *)dst;
        for (size_t i = 0; i < block_count; ++i)
        {
            err = zyp_sdmmc_read_sectors_dma(cmd, card, requestbuffer, tmp_buf, start_block + i, 1);
            if (err != ESP_OK)
            {
                ESP_LOGD(TAG, "%s: error 0x%x writing block %d+%d",
                         __func__, err, start_block, i);
                break;
            }
            memcpy(cur_dst, tmp_buf, block_size);
            cur_dst += block_size;
        }
        free(tmp_buf);
    }
    return err;
}

esp_err_t zyp_mmc_hanlde_write_protect_or_type(sdmmc_card_t *card, sdmmc_command_t *cmd, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer, uint8_t *read_bufer, uint8_t read_size)
{
    esp_err_t err;
    // sdmmc_command_t cmd_read_block_cmd = {
    //     .opcode = requestbuffer->cmdId,
    //     .flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_CMD_READ, /// .flags recacultor  in zyp_sdmmc_read_sectors_dma
    //     .blklen = EXT_CSD_MMC_SIZE,
    //     .datalen = read_size,
    //     .data = (void *)read_bufer,
    //     .timeout_ms = SDMMC_WRITE_CMD_TIMEOUT_MS,
    //     .arg = requestbuffer->cmdParm,
    //     // .no_need_auto_stop = 0,
    // };
    cmd->opcode = requestbuffer->cmdId;
    cmd->flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_CMD_READ;
    cmd->blklen = EXT_CSD_MMC_SIZE;
    cmd->datalen = read_size;
    cmd->data = read_bufer;
    cmd->timeout_ms = SDMMC_WRITE_CMD_TIMEOUT_MS;
    cmd->arg = requestbuffer->cmdParm;
    cmd->no_need_auto_stop = 0;

    err = sdmmc_send_cmd(card, cmd);

    // err = zyp_sdmmc_read_sectors(&cmd_read_block_cmd, card, requestbuffer, read_bufer, requestbuffer->cmdParm, 1); /// param  requestbuffer->cmdParm, 1, no use   todo why  read_size/EXT_CSD_MMC_SIZE is 0？
    // err = zyp_sdmmc_read_sectors(cmd, card, requestbuffer, read_bufer, requestbuffer->cmdParm, 1); /// param  requestbuffer->cmdParm, 1, no use   todo why  read_size/EXT_CSD_MMC_SIZE is 0？

    if (err != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("err read: %s\n", esp_err_to_name(err));
        return err;
    }
    else
    {
        ZYP_DEBUG_VERIFY_CASE(" read buffer_r: \n");
        for (size_t i = 0; i < read_size; i++)
        {
            ZYP_DEBUG_VERIFY_CASE("%02x ", read_bufer[i]);
        }
    }

    return err;
}

/// @brief
/// @param cmd
/// @param card
/// @param requestbuffer
/// @param dst
/// @param start_block   start_block measn cmd arg?
/// @param block_count
/// @return
esp_err_t zyp_sendReadCmd(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, unsigned int *sendReadDataCmdbuffer, size_t start_block, size_t block_count)
{
    if (!cmd || !card || !requestbuffer)
    {
        return ESP_ERR_INVALID_ARG;
    }
    if (block_count == 0)
    {
        return ESP_ERR_INVALID_SIZE;
    }
    if (requestbuffer->cmdId != MMC_EXECUTE_READ_TASK && requestbuffer->cmdId != MMC_READ_BLOCK_SINGLE &&
        requestbuffer->cmdId != MMC_READ_BLOCK_MULTIPLE && requestbuffer->cmdId != MMC_CMD_APP_CMD_2 && requestbuffer->cmdId != MMC_CMD_BUS_TEST_R && requestbuffer->cmdId != MMC_SEND_WRITE_PROT && requestbuffer->cmdId != SEND_WRITE_PROT_TYPE && requestbuffer->cmdId != MMC_SEND_WRITE_PROT)
    {
        return ESP_ERR_NOT_SUPPORTED;
    }

#if IS_ENBAEL_ZYP_DEBUG_MMC
    ZYP_DEBUG_USB("block_count :%d\n", block_count);
    memset(sendReadDataCmdbuffer, 0, block_count * EXT_CSD_MMC_SIZE);

    if (requestbuffer->cmdId == MMC_CMD_BUS_TEST_R)
    {
        ZYP_DEBUG_USB(" block_count * EXT_CSD_MMC_SIZE:%d\n", block_count * EXT_CSD_MMC_SIZE);
        ZYP_DEBUG_USB("\n--------------char read buffer data  defalut  value:--------------\n");
        uint8_t *buffer1 = (uint8_t *)sendReadDataCmdbuffer;
        for (size_t i = 0; i < block_count * EXT_CSD_MMC_SIZE; i++)
        {
            ZYP_DEBUG_USB("%02X ", buffer1[i]);
        }
        ZYP_DEBUG_USB("\n\n\n");

        ZYP_DEBUG_USB("\n--------------unsigned int read buffer data  defalut  value:--------------\n");
        for (size_t i = 0; i < block_count * EXT_CSD_MMC_SIZE; i++)
        {
            ZYP_DEBUG_USB("%02X ", sendReadDataCmdbuffer[i]);
        }
        ZYP_DEBUG_USB("\n\n\n");
    }
#endif

    esp_err_t err = zyp_sdmmc_read_sectors(cmd, card, requestbuffer, (void *)sendReadDataCmdbuffer, start_block, block_count);
    if (requestbuffer->cmdId == MMC_CMD_BUS_TEST_R)
    {
        ZYP_DEBUG_USB("\n--------------read data value:--------------\n");
        uint8_t *buffer1 = (uint8_t *)sendReadDataCmdbuffer;
        for (size_t i = 0; i < block_count * EXT_CSD_MMC_SIZE; i++)
        {
            ZYP_DEBUG_USB("%02X ", buffer1[i]);
        }
        ZYP_DEBUG_USB("\n\n\n");
    }

    if (!err)
    {
#if ZYP_DEBUG_USB
        ZYP_DEBUG_USB(" read data success\n");
        for (size_t i = 0; i < block_count * EXT_CSD_MMC_SIZE; i++)
        {
            ZYP_DEBUG_USB("%02X ", sendReadDataCmdbuffer[i]);
        }
#endif
    }
    else
    {
        ZYP_DEBUG_USB("Error in zyp_sdmmc_read_sectors: %s\n", esp_err_to_name(err));
        // Reset the buffer on error
        // memset(sendReadDataCmdbuffer, 0, block_count * EXT_CSD_MMC_SIZE);
    }
    return err;
}
#endif

esp_err_t zyp_mmc_write_sectors_dma(sdmmc_card_t *card, sdmmc_command_t *cmd, struct RequestBuffer *requestbuffer, const void *src,
                                    size_t start_block, size_t block_count)
{
    // ZYP_DEBUG_VERIFY_CASE("requestbuffer->cmdId:%d ",requestbuffer->cmdId);
#if IS_ENABLE_SEND_CMD_CSD
    if (start_block + block_count > card->csd.capacity)
    {
        return ESP_ERR_INVALID_SIZE;
    }
    size_t block_size = card->csd.sector_size;
#endif

#if !IS_ENABLE_SEND_CMD_CSD
    size_t block_size = EXT_CSD_MMC_SIZE;
#endif

    if (requestbuffer->cmdId == MMC_EXECUTE_WRITE_TASK) /// external  construt parm
    {
        /*code*/
    }

    else if (requestbuffer->cmdId == MMC_LOCK_UNLOCK)
    {
        /*code*/
    }

    else if (requestbuffer->cmdId == MMC_WRITE_BLOCK_MULTIPLE && (cmd->no_need_auto_stop == 1)) /// PD W   or define_end just cmd23 cmd25
    {
        if (requestbuffer->requestDirection == 0x01) /// define_end way
        {
            cmd->data = (void *)src;
        }

        // if (requestbuffer->cmdParm ==0XFE)
        // {
        //     /* code */
        // }

        /// else pd_w  external structure
    }

    // else if (requestbuffer->cmdId == MMC_SEND_WRITE_PROT || requestbuffer->cmdId == SEND_WRITE_PROT_TYPE) /// external structure
    // {
    //     ZYP_DEBUG_MMC("MMC_SEND_WRITE_PROT | SEND_WRITE_PROT_TYPE\n ");
    // }

    else
    {
#if 1
        ZYP_DEBUG_VERIFY_CASE("nomal cmd25 auto cmd12\n"); /// open end
        cmd->arg = requestbuffer->cmdParm;
        cmd->opcode = requestbuffer->cmdId;
        cmd->blklen = block_size;
        cmd->data = (void *)src;
        cmd->datalen = block_count * block_size;
        cmd->timeout_ms = SDMMC_WRITE_CMD_TIMEOUT_MS;
        ZYP_DEBUG_VERIFY_CASE("cmd->datalen:%d\n", cmd->datalen);
#endif
    }

#if 0 
    if (card->ocr & SD_OCR_SDHC_CAP)
    {
        cmd->arg = start_block;               ///byte mode 
    }
    else
    {
        cmd->arg = start_block * block_size;  ///block mode
    }
#endif

    esp_err_t err = sdmmc_send_cmd(card, cmd);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "%s: sdmmc_send_cmd returned 0x%x", __func__, err);
        return err;
    }
    ZYP_DEBUG_MMC("test2\n");
    size_t count = 0;
    const int64_t timeout_us = 2 * 1000 * 1000; // timeout
    int64_t t0 = esp_timer_get_time();
    uint32_t status = 0;

    ZYP_DEBUG_MMC("slot_config GPIO d0:%d\n", slot_config.d0);
    ZYP_DEBUG("GPIO d0 defalut level:%d\n", gpio_get_level(slot_config.d0));
    /// wating  write for ready        Add DAT0 busy detection after each CMD25 (instead of a fixed delay)
    ZYP_DEBUG_MMC("test3\n");
#if 1

    if (cmd->opcode != MMC_CMD_APP_CMD_2)
    {
        /// just  cmd25  judge?
        ZYP_DEBUG("cmd_arg:%d\n", (size_t)cmd->arg);
        while (1)
        {
            if (card->log_bus_width == LOG_BUS_WITH_8BIT || card->log_bus_width == LOG_BUS_WITH_4BIT || card->log_bus_width == LOG_BUS_WITH_1BIT)
            {
                if (gpio_get_level(slot_config.d0) == 0)
                {                                   // DAT0 low busy data is transfering
                    vTaskDelay((pdMS_TO_TICKS(5))); // free CPU
                    continue;
                }
            }
            if (esp_timer_get_time() - t0 > SDMMC_READY_FOR_DATA_TIMEOUT_US_FREAM)
            {
                ESP_LOGE(TAG, "Wait timeout after CMD%d", (size_t)cmd->opcode);
                return ESP_ERR_TIMEOUT;
            }
            else
            {
                break;
            }
        }
    }

#endif
    if (cmd->opcode == MMC_WRITE_BLOCK_MULTIPLE) /// cmd23的话就直接返回cmd23 resp  if cmd25 send cmd13 返回cmd13的 resp
    {
        err = zyp_mmc_send_cmd_send_status(card, cmd, &status);
        if (err != ESP_OK)
        {
            ESP_LOGE(TAG, "%s: zyp_mmc_send_cmd_send_status returned 0x%x", __func__, err);
            return err;
        }
        if (++count % 16 == 0)
        {
            ESP_LOGV(TAG, "waiting for card to become ready (%d)", count);
        }
    }

#if IS_ENABLE_CHECKA_STATUS
    int64_t yield_delay_us = 100 * 1000; // initially 100ms
    int64_t t0 = esp_timer_get_time();
    int64_t t1 = 0; /// time
    while (!host_is_spi(card) && !(status & MMC_R1_READY_FOR_DATA))
    {
        t1 = esp_timer_get_time();
        // if (t1 - t0 > SDMMC_READY_FOR_DATA_TIMEOUT_US)
        if (t1 - t0 > SDMMC_READY_FOR_DATA_TIMEOUT_US_FREAM)
        {
            ZYP_DEBUG_MMC("T0: %lld, T1: %lld\n", t0, t1);
            ESP_LOGE(TAG, "write sectors dma - timeout");
            return ESP_ERR_TIMEOUT;
        }
        if (t1 - t0 > yield_delay_us)
        {
            yield_delay_us *= 2;
            vTaskDelay(1);
        }
        if (cmd->opcode == MMC_WRITE_BLOCK_MULTIPLE) /// cmd23的话就直接返回cmd23 resp  if cmd25 send cmd13 返回cmd13的 resp
        {
            err = zyp_mmc_send_cmd_send_status(card, cmd, &status);
            if (err != ESP_OK)
            {
                ESP_LOGE(TAG, "%s: zyp_mmc_send_cmd_send_status returned 0x%x", __func__, err);
                return err;
            }
            if (++count % 16 == 0)
            {
                ESP_LOGV(TAG, "waiting for card to become ready (%d)", count);
            }
        }
    }
    if (host_is_spi(card))
    {
        if (cmd->opcode == MMC_WRITE_BLOCK_MULTIPLE)
        {
            err = zyp_mmc_send_cmd_send_status(card, cmd, &status);
            if (err != ESP_OK)
            {
                ESP_LOGE(TAG, "%s: zyp_mmc_send_cmd_send_status returned 0x%x", __func__, err);
                return err;
            }
            if (status & SD_SPI_R2_CARD_LOCKED)
            {
                ESP_LOGE(TAG, "%s: write failed, card is locked: r2=0x%04lx",
                         __func__, status);
                return ESP_ERR_INVALID_STATE;
            }
            if (status != 0)
            {
                ESP_LOGE(TAG, "%s: card status indicates an error after write operation: r2=0x%04lx",
                         __func__, status);
                return ESP_ERR_INVALID_RESPONSE;
            }
        }
    }
#endif
    return ESP_OK;
}

esp_err_t zyp_mmc_write_sectors(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, const void *src,
                                size_t start_block, size_t block_count)
{

    if (block_count == 0)
    {
        return ESP_OK;
    }

    esp_err_t err = ESP_OK;
#if IS_ENABLE_SEND_CMD_CSD
    size_t block_size = card->csd.sector_size;
#endif
#if !IS_ENABLE_SEND_CMD_CSD
    size_t block_size = EXT_CSD_MMC_SIZE;
#endif

#if 1
    bool is_dma_capable = esp_ptr_dma_capable(src); /// dma addr range: SOC_DMA_HIGH - SOC_DMA_LOW  491520KB  480KB
    bool is_4byte_aligned = ((intptr_t)src % 4 == 0);
    ESP_LOGI("TAG", "point addr: 0x%08" PRIxPTR, (uintptr_t)src);
    ESP_LOGI("TAG", "at DMA range: %s", is_dma_capable ? "yes" : "no");
    ESP_LOGI("TAG", "addr is 4 byte aligned: %s", is_4byte_aligned ? "yes" : "no");
    ESP_LOGI("TAG", "actually aligned cnt: %" PRIuPTR, (uintptr_t)src % 4);
#endif

    if (esp_ptr_dma_capable(src) && (intptr_t)src % 4 == 0) /// cheak src adddr loaciton DMA low and DMA highest,and addr must 4byte aligned
    {
        ZYP_DEBUG_MMC("4byte aligned\n");
        err = zyp_mmc_write_sectors_dma(card, cmd, requestbuffer, src, start_block, block_count);
    }
    else
    {
        ZYP_DEBUG_MMC(" not 4byte aligned\n");
#if MMC_WRITE_SEDND
        void *tmp_buf = heap_caps_malloc(block_size * block_count, MALLOC_CAP_DMA);
#endif

#if !MMC_WRITE_SEDND
        void *tmp_buf = heap_caps_malloc(block_size, MALLOC_CAP_DMA);
#endif

        ZYP_DEBUG_MMC("heap_caps_malloc\n");
        if (tmp_buf == NULL)
        {
            return ESP_ERR_NO_MEM;
        }
        ZYP_DEBUG_MMC("%d \n", __LINE__);
#if !MMC_WRITE_SEDND
        const uint8_t *cur_src = (const uint8_t *)src;
        for (size_t i = 0; i < block_count; ++i)
        {
            memcpy(tmp_buf, cur_src, block_size * block_count);
            ZYP_DEBUG_MMC("memcpy %d\n", i);
            cur_src += block_size;
            err = zyp_mmc_write_sectors_dma(card, cmd, requestbuffer, tmp_buf, start_block + i, 1);
            if (err != ESP_OK)
            {
                ESP_LOGD(TAG, "%s: error 0x%x writing block %d+%d",
                         __func__, err, start_block, i);
                return ESP_FAIL;
            }
        }
        free(tmp_buf);
#endif

#if MMC_WRITE_SEDND
        const uint8_t *cur_src = (const uint8_t *)src;
        memcpy(tmp_buf, cur_src, block_size * block_count);
        err = zyp_mmc_write_sectors_dma(card, cmd, requestbuffer, tmp_buf, start_block, block_count);
        if (err != ESP_OK)
        {
            return ESP_FAIL;
        }
        free(tmp_buf);
#endif
    }
    return err;
}

esp_err_t zyp_sendWriteCmd(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct RwReciveBuffer *rwRecivebuffer, size_t data_cmd_cnt)
{
    if (!cmd || !card || !requestbuffer || !rwRecivebuffer)
    {
        return ESP_ERR_INVALID_ARG;
    }
    if (data_cmd_cnt == 0)
    {
        return ESP_ERR_INVALID_SIZE;
    }
    if (requestbuffer->cmdId != MMC_WRITE_BLOCK_SINGLE &&
        requestbuffer->cmdId != MMC_WRITE_BLOCK_MULTIPLE)
    {
        return ESP_ERR_NOT_SUPPORTED;
    }
    ZYP_DEBUG_DATA("\n--------------rwRecivebuffer->data value:--------------\n");
    /// 将 rwRecivebuffer->data
    char *data = (char *)rwRecivebuffer->data;
    for (size_t i = 0; i < data_cmd_cnt * EXT_CSD_MMC_SIZE; i++)
    {
        ZYP_DEBUG_DATA("%02X ", (unsigned int)data[i]);
    }
    ZYP_DEBUG_DATA("\n");

    ZYP_DEBUG_DATA("\n--------------cmd_data value:--------------\n");
    // cmd_data
    for (size_t i = 0; i < data_cmd_cnt * EXT_CSD_MMC_SIZE; i++)
    {
        ZYP_DEBUG_DATA("%02X ", cmd_data[i]);
    }
    ZYP_DEBUG_DATA("\n");

    return zyp_mmc_write_sectors(cmd, card, requestbuffer, rwRecivebuffer->data,
                                 requestbuffer->cmdParm, (requestbuffer->cmdId == MMC_WRITE_BLOCK_SINGLE) ? 1 : data_cmd_cnt);
#if 0
    free(cmd_data);
    int err = ESP_FAIL;
    if (data_cmd_cnt == 1 && requestbuffer->cmdId == MMC_WRITE_BLOCK_SINGLE)
    {
        return zyp_mmc_write_sectors(cmd, card, requestbuffer, rwRecivebuffer->data, requestbuffer->cmdParm, 1);
    }
    else if (requestbuffer->cmdId == MMC_WRITE_BLOCK_MULTIPLE && data_cmd_cnt >= 1)
    {
        return zyp_mmc_write_sectors(cmd, card, requestbuffer, rwRecivebuffer->data, requestbuffer->cmdParm, data_cmd_cnt);
    }
#endif
}

esp_err_t zyp_mmc_set_blocklen_cmd_fream(sdmmc_card_t *card, sdmmc_command_t *cmd, struct RequestBuffer *requestbuffer)
{
    cmd->data = NULL;
    cmd->opcode = requestbuffer->cmdId;
    cmd->arg = requestbuffer->cmdParm;
    cmd->flags = SCF_CMD_AC | SCF_RSP_R1;
    return sdmmc_send_cmd(card, cmd);
}

esp_err_t zyp_sdmmc_mmc_send_ext_csd_data(sdmmc_card_t *card, void *out_data, size_t datalen, sdmmc_command_t *cmd, struct RequestBuffer *requestbuffer)
{
    ZYP_DEBUG_MMC("zyp_sdmmc_mmc_send_ext_csd_data\n");
    assert(esp_ptr_dma_capable(out_data));
    cmd->arg = requestbuffer->cmdParm;
    cmd->data = out_data;
    cmd->datalen = datalen;
    cmd->blklen = datalen;
    cmd->opcode = requestbuffer->cmdId;
    cmd->flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_CMD_READ;
    return sdmmc_send_cmd(card, cmd);
}

esp_err_t zyp_sdmmc_init_mmc_read_ext_csd(sdmmc_card_t *card, sdmmc_command_t *cmd, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer, uint8_t *ext_csd)
{
    int card_type;
    esp_err_t err = ESP_OK;
    uint32_t sectors = 0;

    ZYP_DEBUG_MMC("MMC version: %d\n", card->csd.mmc_ver);

#if IS_ENABLE_SEND_CMD_CSD
    if (card->csd.mmc_ver < MMC_CSD_MMCVER_4_0) /// must send cmd9 csd !!!!
    {
        err = ESP_ERR_NOT_SUPPORTED;
        goto out;
    }
#endif

    err = zyp_sdmmc_mmc_send_ext_csd_data(card, ext_csd, EXT_CSD_MMC_SIZE, cmd, requestbuffer);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_MMC(TAG, "%s: send_ext_csd_data error 0x%x", __func__, err);
        goto out;
    }

    card_type = ext_csd[EXT_CSD_CARD_TYPE]; /// after read over accroding to ext_csd value set host same veriable suchas  card
    card->is_ddr = 0;
    if (card_type & EXT_CSD_CARD_TYPE_F_52M_1_8V)
    {
        card->max_freq_khz = SDMMC_FREQ_52M;
        if ((card->host.flags & SDMMC_HOST_FLAG_DDR) &&
            card->host.max_freq_khz >= SDMMC_FREQ_26M &&
            card->host.get_bus_width(card->host.slot) == 4)
        {
            ESP_LOGD(TAG, "card and host support DDR mode");
            card->is_ddr = 1;
        }
    }
    else if (card_type & EXT_CSD_CARD_TYPE_F_52M)
    {
        card->max_freq_khz = SDMMC_FREQ_52M;
    }
    else if (card_type & EXT_CSD_CARD_TYPE_F_26M)
    {
        card->max_freq_khz = SDMMC_FREQ_26M;
    }
    else
    {
        ESP_LOGW(TAG, "%s: unknown CARD_TYPE 0x%x", __func__, card_type);
    }
    /* For MMC cards, use speed value from EXT_CSD */
    card->csd.tr_speed = card->max_freq_khz * 1000;
    ESP_LOGD(TAG, "MMC card type %d, max_freq_khz=%d, is_ddr=%d", card_type, (size_t)card->max_freq_khz, (size_t)card->is_ddr);
    card->max_freq_khz = MIN(card->max_freq_khz, card->host.max_freq_khz);

    if (card->host.flags & SDMMC_HOST_FLAG_8BIT)
    {
        card->ext_csd.power_class = ext_csd[(card->max_freq_khz > SDMMC_FREQ_26M) ? EXT_CSD_PWR_CL_52_360 : EXT_CSD_PWR_CL_26_360] >> 4;
        card->log_bus_width = 3;
    }
    else if (card->host.flags & SDMMC_HOST_FLAG_4BIT)
    {
        card->ext_csd.power_class = ext_csd[(card->max_freq_khz > SDMMC_FREQ_26M) ? EXT_CSD_PWR_CL_52_360 : EXT_CSD_PWR_CL_26_360] & 0x0f;
        card->log_bus_width = 2;
    }
    else
    {
        card->ext_csd.power_class = 0; // card must be able to do full rate at powerclass 0 in 1-bit mode
        card->log_bus_width = 0;
    }

    sectors = (ext_csd[EXT_CSD_SEC_COUNT + 0] << 0) | (ext_csd[EXT_CSD_SEC_COUNT + 1] << 8) | (ext_csd[EXT_CSD_SEC_COUNT + 2] << 16) | (ext_csd[EXT_CSD_SEC_COUNT + 3] << 24);

    if (sectors > (2u * 1024 * 1024 * 1024) / 512)
    {
        card->csd.capacity = sectors;
    }

    /* erased state of a bit, if 1 byte value read is 0xFF else 0x00 */
    card->ext_csd.erase_mem_state = ext_csd[EXT_CSD_ERASED_MEM_CONT];
    card->ext_csd.rev = ext_csd[EXT_CSD_REV];
    card->ext_csd.sec_feature = ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT];
out:
    //     free(ext_csd);
    return err;
}

void zyp_CmdStatus_wrappeRespnceDataFrameAndSendHex_nostruct(struct RequestBuffer *requestbuffer, uint8_t *sendReadDataCmdbuffer, unsigned int sendReadDataCmdbufferSize)
{
    int i = 0;
    ZYP_DEBUG_MMC("recive buffer size:%d\n", sendReadDataCmdbufferSize);
    ZYP_DEBUG_MMC("orignal recive data:\n");
    for (i = 0; i < sendReadDataCmdbufferSize; i++)
    {
        ZYP_DEBUG_MMC("%02X,", sendReadDataCmdbuffer[i]); ///
    }

    ZYP_DEBUG_MMC("\n\n");
    int rwReqequtBufferSize = MMC_DATA_CMD_FREAM_BASIC_SIZE + sendReadDataCmdbufferSize; // 8 Basic Length + 512*sendReadDataCmdbufferSize
    char *ext_csd_data_buffer_fream = (char *)malloc(rwReqequtBufferSize);               // Dynamic memory allocation
    if (ext_csd_data_buffer_fream == NULL)
    {
        ZYP_DEBUG_MMC("Failed to allocate memory");
        return; // Or handle the error as needed
    }

    memset(ext_csd_data_buffer_fream, 0, rwReqequtBufferSize);
    ext_csd_data_buffer_fream[0] = MMC_DATA_CMD_FREAM_START_BYTE;
    ext_csd_data_buffer_fream[1] = MMC_DATA_CMD_FREAM_TANSFER_SLAVE_TO_HOST_FLAG;
    ext_csd_data_buffer_fream[2] = MMC_DATA_CMD_FREAM_TANSFER_SLAVE_TO_HOST_RWFLAG; /// 03
    ext_csd_data_buffer_fream[3] = sendReadDataCmdbufferSize / EXT_CSD_MMC_SIZE;
    ext_csd_data_buffer_fream[rwReqequtBufferSize - 4] = MMC_DATA_CMD_FREAM_ENDMARK_ONEBYTE;
    ext_csd_data_buffer_fream[rwReqequtBufferSize - 3] = MMC_DATA_CMD_FREAM_ENDMARK_TWOBYTE;
    ext_csd_data_buffer_fream[rwReqequtBufferSize - 2] = MMC_DATA_CMD_FREAM_ENDMARK_THREEBYTE;
    ext_csd_data_buffer_fream[rwReqequtBufferSize - 1] = MMC_DATA_CMD_FREAM_ENDMARK_FOURBYTE; /// end bit
    memcpy(ext_csd_data_buffer_fream + 4, sendReadDataCmdbuffer, sendReadDataCmdbufferSize);  /// copy data

    for (i = 0; i < rwReqequtBufferSize; i++)
    {
        ZYP_DEBUG_MMC("%02X,", ext_csd_data_buffer_fream[i]);
    }
    ZYP_DEBUG_MMC("\n\n\n");
    zyp_tinyusb_cdcacm_write_queue(0, (uint8_t *)ext_csd_data_buffer_fream, rwReqequtBufferSize);
    free(ext_csd_data_buffer_fream);
}

esp_err_t zyp_sendCmd_EXT_CSD_RespData(sdmmc_card_t *card, sdmmc_command_t *cmd, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer)
{
    esp_err_t err = ESP_OK;
    uint8_t *ext_csd = heap_caps_malloc(EXT_CSD_MMC_SIZE, MALLOC_CAP_DMA);
    if (!ext_csd)
    {
        ZYP_LOG_ERR(ZYP_LOG_LEVEL_ERR, "could not allocate memory for ext_csd\n");
        // goto out;
        return err;
    }
    memset(ext_csd, 0, EXT_CSD_MMC_SIZE);

#if 1
    zyp_sdmmc_init_mmc_read_ext_csd(card, cmd, requestbuffer, responsebuffer, ext_csd);
    zyp_wrappeRespnceCmdFrameAndSendHex(cmd, requestbuffer, responsebuffer);
    zyp_CmdStatus_wrappeRespnceDataFrameAndSendHex_nostruct(requestbuffer, ext_csd, EXT_CSD_MMC_SIZE);
#endif

#if 0
    if (!zyp_sdmmc_init_mmc_read_ext_csd(card, cmd, requestbuffer, responsebuffer, ext_csd))
    {
        ZYP_DEBUG_MMC("ext_csd read sucess\n");
        zyp_wrappeRespnceCmdFrameAndSendHex(cmd, requestbuffer, responsebuffer);
        zyp_CmdStatus_wrappeRespnceDataFrameAndSendHex_nostruct(requestbuffer, ext_csd, EXT_CSD_MMC_SIZE);
    }
    else
    {
        ZYP_DEBUG_MMC("ext_csd read fail\n");
        zyp_wrappeRespnceCmdR_W_Err_FrameAndSendHex(cmd, requestbuffer, responsebuffer);
    }
#endif
    if (ext_csd != NULL)
    {
        free(ext_csd);
    }
    return err;
}

esp_err_t zyp_sdmmc_send_cmd_set_relative_addr_handlefream(sdmmc_card_t *card, sdmmc_command_t *cmd, struct RequestBuffer *requestbuffer, uint16_t *out_rca)
{
    assert(out_rca);
    card->is_mmc = 1;
    cmd->arg = requestbuffer->cmdParm;
    cmd->data = NULL; /// must be null  if not  cmd send err why not vrigin flow is ok?
    cmd->flags = SCF_CMD_BCR | SCF_RSP_R6;
#if IS_ENABLE_MMC_FUNCTION_DEBUG
    ZYP_DEBUG_MMC("is_mmc:%d,cmd->opcode:%lx,cmd->arg:%lx,cmd->flags:%x\n", card->is_mmc, cmd->opcode, cmd->arg, cmd->flags);
#endif

#if 0   
    if (card->is_mmc)
    {
        cmd->arg = MMC_ARG_RCA(mmc_rca);
    }
#endif

    esp_err_t err = sdmmc_send_cmd(card, cmd);
    if (err != ESP_OK)
    {
        return err;
    }

    if (card->is_mmc)
    {
        *out_rca = (cmd->arg >> 16) & 0xFFFF;
    }
    else
    {
        uint16_t response_rca = SD_R6_RCA(cmd->response);
        if (response_rca == 0)
        {
            // err = sdmmc_send_cmd(card, &cmd);
            err = sdmmc_send_cmd(card, cmd);
            if (err != ESP_OK)
            {
                return err;
            }
            response_rca = SD_R6_RCA(cmd->response);
        }
        *out_rca = response_rca;
    }
    return ESP_OK;
}

esp_err_t zyp_sdmmc_send_cmd_send_csd_handlefream(sdmmc_card_t *card, sdmmc_command_t *cmd, struct RequestBuffer *requestbuffer, sdmmc_csd_t *out_csd)
{
    sdmmc_response_t spi_buf;
    const bool is_spi = host_is_spi(card);

    cmd->opcode = requestbuffer->cmdId;
    cmd->arg = requestbuffer->cmdParm;
    cmd->flags = SCF_CMD_AC | SCF_RSP_R2;
    cmd->data = 0;
    cmd->datalen = 0;
#if 0    
    cmd->arg = is_spi ? 0 : MMC_ARG_RCA(card->rca);
    cmd->flags = is_spi ? (SCF_CMD_READ | SCF_CMD_ADTC | SCF_RSP_R1) : (SCF_CMD_AC | SCF_RSP_R2);
    cmd->data = is_spi ? &spi_buf[0] : 0;
    cmd->datalen = is_spi ? sizeof(spi_buf) : 0;
#endif

    esp_err_t err = sdmmc_send_cmd(card, cmd);
    if (err)
    {
        return err;
    }
    uint32_t *ptr = cmd->response;
    if (is_spi)
    {
        sdmmc_flip_byte_order(spi_buf, sizeof(spi_buf));
        ptr = spi_buf;
    }
    if (card->is_mmc)
    {
        err = sdmmc_mmc_decode_csd(cmd->response, out_csd);
    }
    else
    {
        err = sdmmc_decode_csd(ptr, out_csd);
    }
    return err;
}

void zyp_handle_mmc_cmd_response(sdmmc_command_t *cmd, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer, bool is_error)
{
    if (is_error)
    {
        ZYP_DEBUG_MMC("zyp_sendNomalCmd cmd:%d\n", (unsigned int)cmd->opcode);
        zyp_wrappeRespnceCmdR_W_Err_FrameAndSendHex(cmd, requestbuffer, responsebuffer);
    }
    else
    {
        zyp_wrappeRespnceCmdFrameAndSendHex(cmd, requestbuffer, responsebuffer);
    }
    memset(requestbuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct RequestBuffer));
    memset(responsebuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct ResponseBuffer));
}

esp_err_t zyp_sendCmd19AndRespFrame(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer)
{
    // zyp_sdmmc_configure_bus_fre_mode(card, 50, card->host.get_bus_width(card->host.slot), 0);

    int j = 0;

#if MMMC_SCHEME_BUSTEST
    uint8_t *test_buf = heap_caps_malloc(BUS_TEST_DATA_SIZE, MALLOC_CAP_DMA);
    uint8_t *test_buf_data = heap_caps_malloc(EXT_CSD_MMC_SIZE, MALLOC_CAP_DMA);
#else
    uint8_t *test_buf = heap_caps_aligned_alloc(4, BUS_TEST_DATA_SIZE,
                                                MALLOC_CAP_DMA);
    uint8_t *test_buf_data = heap_caps_aligned_alloc(4, EXT_CSD_MMC_SIZE,
                                                     MALLOC_CAP_DMA);

#endif

    memset(test_buf, 0, BUS_TEST_DATA_SIZE);
    memset(test_buf_data, 0, EXT_CSD_MMC_SIZE);

    cmd->opcode = requestbuffer->cmdId;
    cmd->arg = requestbuffer->cmdParm;
    cmd->flags = SCF_CMD_ADTC | SCF_RSP_R1;
    ZYP_DEBUG_USB("current log mmc->bus_width:%02X\n", (size_t)card->log_bus_width);
    if ((card->log_bus_width) == LOG_BUS_WITH_8BIT)
    {
        test_buf[0] = 0xAA;
        test_buf[1] = 0X55;
        test_buf[0] = rwRecivebuffer.data[0];
        test_buf[1] = rwRecivebuffer.data[1];
        memcpy(test_buf_data, test_buf, BUS_WITH_8BIT);
    }
    else if ((card->log_bus_width) == LOG_BUS_WITH_4BIT)
    {
        test_buf[0] = 0x5A;
        test_buf[0] = rwRecivebuffer.data[0];
        memcpy(test_buf_data, test_buf, BUS_WITH_4BIT);
    }
    else
    {
        test_buf[0] = 0X80;
        test_buf[0] = rwRecivebuffer.data[0];
        memcpy(test_buf_data, test_buf, BUS_WITH_1BIT);
    }
    ZYP_DEBUG_USB("origal mybuffer  is \n");
    for (j = 0; j < BUS_TEST_DATA_SIZE; j++)
    {
        ZYP_DEBUG_USB("%02X ", test_buf_data[j]);
        if (j == BUS_TEST_DATA_SIZE - 1)
        {
            ZYP_DEBUG_USB("\n\n");
        }
    }

#if MMMC_SCHEME_BUSTEST
    esp_err_t err = zyp_mmc_write_sectors(cmd, card, requestbuffer, test_buf_data, 0, 1); /// todo add is 0? and is how?
#else
    cmd->data = test_buf_data;
    cmd->datalen = EXT_CSD_MMC_SIZE;
    cmd->blklen = EXT_CSD_MMC_SIZE;
    esp_err_t err = sdmmc_send_cmd(card, cmd);
    ZYP_DEBUG_USB("err:%d,%s\n", err, esp_err_to_name(err));
#endif
    if (test_buf != NULL)
    {
        free(test_buf);
    }
    if (test_buf_data != NULL)
    {
        free(test_buf_data);
    }
    return err;
}

esp_err_t zyp_sendCmd14AndRespFrame(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer)
{
    int j = 0;
    uint8_t *mybuffer = heap_caps_malloc(EXT_CSD_MMC_SIZE, MALLOC_CAP_DMA);
    memset(mybuffer, 0, EXT_CSD_MMC_SIZE);
    ZYP_DEBUG_MMC("\n--------------mybuffer  value:--------------\n");
    for (size_t i = 0; i < EXT_CSD_MMC_SIZE; i++)
    {
        ZYP_DEBUG_MMC("%02X ", mybuffer[i]);
    }
    ZYP_DEBUG_MMC("\n\n\n");

    cmd->opcode = requestbuffer->cmdId;
    cmd->arg = requestbuffer->cmdParm;
    cmd->flags = SCF_CMD_READ | SCF_RSP_R1;

#if MMMC_SCHEME_BUSTEST
    esp_err_t err = zyp_sendReadCmd(cmd, card, requestbuffer, (unsigned int *)mybuffer, requestbuffer->cmdParm, 1);
#else
    cmd->data = EXT_CSD_MMC_SIZE;
    cmd->datalen = EXT_CSD_MMC_SIZE;
    cmd->flags = SCF_CMD_READ | SCF_RSP_R1 | SCF_CMD_ADTC;
    esp_err_t err = sdmmc_send_cmd(card, cmd);

#endif
    ZYP_DEBUG_MMC("send cmd emmc resp: \n");
    for (j = 0; j < 16; j++)
    {
        ZYP_DEBUG_MMC("cmd->response[%d]:%08X\n ", j, (unsigned int)cmd->response[j]);
    }
    ZYP_DEBUG_MMC("\n");
    zyp_wrappeRespnceCmdFrameAndSendHex(cmd, requestbuffer, responsebuffer);

    if ((card->log_bus_width) == LOG_BUS_WITH_8BIT)
    {
        memset(mybuffer + BUS_TEST_DATA_GET_VALID_BYTE, 0, BUS_WITH_8BIT - BUS_TEST_DATA_GET_VALID_BYTE);
    }
    else if ((card->log_bus_width) == LOG_BUS_WITH_4BIT || (card->log_bus_width) == LOG_BUS_WITH_1BIT)
    {
        memset(mybuffer + BUS_TEST_DATA_GET_VALID_BYTE - 1, 0, BUS_WITH_8BIT - BUS_TEST_DATA_GET_VALID_BYTE);
    }
    zyp_wrappeRespnceDataFrameAndSendHex_nostruct(requestbuffer, (char *)mybuffer, BUS_WITH_8BIT);

#if 0   
    if (!err)
    {
        // CMD RESP
        ZYP_DEBUG_MMC("read cmd14 bus_test data\n");
        zyp_wrappeRespnceCmd14Resp(cmd, card, requestbuffer, responsebuffer, (char *)mybuffer);
    }
    else
    {
        zyp_wrappeRespnceCmdR_W_Err_FrameAndSendHex(cmd, requestbuffer, responsebuffer);
        // Reset the buffer on error
        memset(mybuffer, 0, EXT_CSD_MMC_SIZE);
    }
#endif

    if (mybuffer != NULL)
    {
        free(mybuffer);
    }
    return err;
}

esp_err_t zyp_sendCmdPro_CIDOrCSD_RespCmdFrame(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer, struct RwReciveBuffer *rwRecivebuffer)
{
    int j;
    esp_err_t err;

    if (rwRecivebuffer->data == NULL)
    {
        ZYP_DEBUG_VERIFY_CASE("rwRecivebuffer->data ==NULL\n");
        return ESP_FAIL;
    }

    for (size_t i = 0; i < 16; i++)
    {
        ZYP_DEBUG_VERIFY_CASE("%02x ", rwRecivebuffer->data[i]);
    }

    ZYP_DEBUG_VERIFY_CASE("%d\n", __LINE__);
    uint8_t *bufferarrdata = heap_caps_malloc(EXT_CSD_MMC_SIZE, MALLOC_CAP_DMA);
    // heap_caps_aligned_alloc
    // uint8_t *bufferarrdata = heap_caps_aligned_alloc(4, EXT_CSD_MMC_SIZE,
    //                                                  MALLOC_CAP_DMA | MALLOC_CAP_8BIT);
    if (bufferarrdata == NULL)
    {
        ZYP_DEBUG_MMC("Failed to allocate DMA buffer");
        goto cleanup;
    }
    ZYP_DEBUG_VERIFY_CASE("%d\n", __LINE__);
    uintptr_t addr = (uintptr_t)bufferarrdata;
    // if (addr % 4 != 0)
    // {
    //     ZYP_DEBUG_MMC("Buffer not 4-byte aligned: %p", bufferarrdata);
    //     heap_caps_free(bufferarrdata);
    //     return ESP_FAIL;
    // }
    memset(bufferarrdata, 0, EXT_CSD_MMC_SIZE);
    memcpy(bufferarrdata, rwRecivebuffer->data, MMC_PROGRAM_CID_CSD_DATASIZE);
    ZYP_DEBUG_VERIFY_CASE("%d\n", __LINE__);
    cmd->opcode = requestbuffer->cmdId;
    cmd->arg = requestbuffer->cmdParm;
    cmd->flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_RSP_BSY;
    cmd->blklen = MMC_PROGRAM_CID_CSD_DATASIZE;
    cmd->datalen = MMC_PROGRAM_CID_CSD_DATASIZE;
    // cmd->blklen = EXT_CSD_MMC_SIZE;
    // cmd->datalen = EXT_CSD_MMC_SIZE;
    cmd->data = bufferarrdata;
    cmd->timeout_ms = 5000;

    ZYP_DEBUG_MMC("test data:");
    for (int i = 0; i < MMC_PROGRAM_CID_CSD_DATASIZE; i++)
    {
        ZYP_DEBUG_MMC("%02X ", bufferarrdata[i]);
    }
    ZYP_DEBUG_MMC("\n");
    err = sdmmc_send_cmd(card, cmd);

    ZYP_DEBUG_MMC("CMD response:\n");
    for (j = 0; j < 4; j++)
    {
        ZYP_DEBUG_MMC("response[%d]: 0x%08X\n", j, (size_t)cmd->response[j]);
    }

    zyp_wrappeRespnceCmdFrameAndSendHex(cmd, requestbuffer, responsebuffer);
#if 0    
    if (err != ESP_OK)
    {
        ZYP_DEBUG_MMC("sdmmc_send_cmd returned 0x%x\n", err);

        goto cleanup;
    }
    else
    {
        zyp_wrappeRespnceCmdFrameAndSendHex(cmd, requestbuffer, responsebuffer);
    }
#endif
    if (bufferarrdata != NULL)
    {
        free(bufferarrdata);
        bufferarrdata = NULL;
    }

cleanup:
    if (bufferarrdata != NULL)
    {
        free(bufferarrdata);
        bufferarrdata = NULL;
        return ESP_FAIL;
    }
    return ESP_OK;
}

esp_err_t zyp_sendCmd56W(sdmmc_command_t *cmd, sdmmc_card_t *card,
                         struct RequestBuffer *requestbuffer,
                         struct RwReciveBuffer *rwRecivebuffer,
                         size_t data_cmd_cnt)
{

    return zyp_mmc_write_sectors(cmd, card, requestbuffer,
                                 rwRecivebuffer->data,
                                 requestbuffer->cmdParm,
                                 data_cmd_cnt);
}

esp_err_t zyp_sendCmd56R(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer, size_t start_block, size_t block_count)
{
    esp_err_t err;
    unsigned int *sendReadDataCmdbuffer = (unsigned int *)heap_caps_malloc(block_count * EXT_CSD_MMC_SIZE, MALLOC_CAP_DMA);
    memset(sendReadDataCmdbuffer, 0, block_count * EXT_CSD_MMC_SIZE);
    ZYP_DEBUG_MMC("read cmd parm readMultipeCount: %d, fream cnt(read start addr): %d\n", block_count, requestbuffer->cmdParm);
    err = zyp_sendReadCmd(cmd, card, requestbuffer, sendReadDataCmdbuffer, requestbuffer->cmdParm, block_count); // Just don't rely  cmd23 after writeToallmultipeCount_Byte
    ZYP_DEBUG_MMC("err:%s\n", esp_err_to_name(err));
    if (!err)
    {
        zyp_wrappeRespnceCmdFrameAndSendHex(cmd, requestbuffer, responsebuffer);
        zyp_wrappeRespnceDataFrameAndSendHex_nostruct(requestbuffer, (char *)sendReadDataCmdbuffer, block_count * EXT_CSD_MMC_SIZE);
    }
    else
    {
        zyp_handle_mmc_cmd_response(cmd, requestbuffer, responsebuffer, true);
    }
    if (sendReadDataCmdbuffer != NULL)
    {
        free(sendReadDataCmdbuffer); /// assert failed: block_trim_free tlsf.c:504 (block_is_free(block) && "block must be free")  or no free     heapmalloc just noly 100KB  set cmd_data golbal. just be similar to xu4 fream
        sendReadDataCmdbuffer = NULL;
    }
    memset(requestbuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct RequestBuffer));
    memset(responsebuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct ResponseBuffer));
    return ESP_OK;
}

void zyp_configure_pin_gpio_matrix(uint8_t gpio_num, uint8_t gpio_matrix_sig, gpio_mode_t mode, const char *name)
{
    assert(gpio_num != (uint8_t)GPIO_NUM_NC);
    ESP_LOGD(TAG, "using GPIO%d as %s pin", gpio_num, name);
    gpio_reset_pin(gpio_num);
    gpio_set_direction(gpio_num, mode);
    gpio_pulldown_dis(gpio_num);
    if (mode == GPIO_MODE_INPUT || mode == GPIO_MODE_INPUT_OUTPUT)
    {
        esp_rom_gpio_connect_in_signal(gpio_num, gpio_matrix_sig, false);
    }
    if (mode == GPIO_MODE_OUTPUT || mode == GPIO_MODE_INPUT_OUTPUT)
    {
        esp_rom_gpio_connect_out_signal(gpio_num, gpio_matrix_sig, false, false);
    }
}

static esp_err_t zyp_sdmmc_host_pullup_en_internal(int slot, int width)
{
    if (width > sdmmc_slot_info[slot].width)
    {
        return ESP_ERR_INVALID_ARG;
    }
    gpio_pullup_en(GPIO_NUMS(slot, cmd));
    gpio_pullup_en(GPIO_NUMS(slot, d0));
    if (width >= 4)
    {
        gpio_pullup_en(GPIO_NUMS(slot, d1));
        gpio_pullup_en(GPIO_NUMS(slot, d2));
        gpio_pullup_en(GPIO_NUMS(slot, d3));
    }
    if (width == 8)
    {
        gpio_pullup_en(GPIO_NUMS(slot, d4));
        gpio_pullup_en(GPIO_NUMS(slot, d5));
        gpio_pullup_en(GPIO_NUMS(slot, d6));
        gpio_pullup_en(GPIO_NUMS(slot, d7));
    }
    return ESP_OK;
}

#if 1
esp_err_t zyp_sdmmc_host_init_config_slot(int slot, const sdmmc_slot_config_t *slot_config)
{

    if (!(slot == 0 || slot == 1))
    {
        return ESP_ERR_INVALID_ARG;
    }
    if (slot_config == NULL)
    {
        return ESP_ERR_INVALID_ARG;
    }
    int gpio_cd = slot_config->cd;
    int gpio_wp = slot_config->wp;
    uint8_t slot_width = slot_config->width;

    // Configure pins
    const sdmmc_slot_info_t *slot_info = &sdmmc_slot_info[slot];

    if (slot_width == SDMMC_SLOT_WIDTH_DEFAULT)
    {
        slot_width = slot_info->width;
    }
    else if (slot_width > slot_info->width)
    {
        return ESP_ERR_INVALID_ARG;
    }
    s_slot_width[slot] = slot_width;

#if SOC_SDMMC_USE_GPIO_MATRIX
    s_sdmmc_slot_gpio_nums[slot].clk = slot_config->clk;
    s_sdmmc_slot_gpio_nums[slot].cmd = slot_config->cmd;
    s_sdmmc_slot_gpio_nums[slot].d0 = slot_config->d0;
    s_sdmmc_slot_gpio_nums[slot].d1 = slot_config->d1;
    if (slot_width >= 4)
    {
        s_sdmmc_slot_gpio_nums[slot].d2 = slot_config->d2;
    }
    s_sdmmc_slot_gpio_nums[slot].d3 = slot_config->d3;
    if (slot_width >= 8)
    {
        s_sdmmc_slot_gpio_nums[slot].d4 = slot_config->d4;
        s_sdmmc_slot_gpio_nums[slot].d5 = slot_config->d5;
        s_sdmmc_slot_gpio_nums[slot].d6 = slot_config->d6;
        s_sdmmc_slot_gpio_nums[slot].d7 = slot_config->d7;
    }
#endif

    bool pullup = slot_config->flags & SDMMC_SLOT_FLAG_INTERNAL_PULLUP;
    if (pullup)
    {
        zyp_sdmmc_host_pullup_en_internal(slot, slot_config->width);
    }

    _configure_pins_(clk, slot, GPIO_MODE_OUTPUT);
    _configure_pins_(cmd, slot, GPIO_MODE_INPUT_OUTPUT);
    _configure_pins_(d0, slot, GPIO_MODE_INPUT_OUTPUT);

    if (slot_width >= 4)
    {
        _configure_pins_(d1, slot, GPIO_MODE_INPUT_OUTPUT);
        _configure_pins_(d2, slot, GPIO_MODE_INPUT_OUTPUT);
        gpio_config_t gpio_conf = {
            .pin_bit_mask = BIT64(GPIO_NUMS(slot, d3)),
            .mode = GPIO_MODE_OUTPUT,
            .pull_up_en = 0,
            .pull_down_en = 0,
            .intr_type = GPIO_INTR_DISABLE,
        };
        gpio_config(&gpio_conf);
        gpio_set_level(GPIO_NUMS(slot, d3), 1);
    }
    if (slot_width == 8)
    {
        _configure_pins_(d4, slot, GPIO_MODE_INPUT_OUTPUT);
        _configure_pins_(d5, slot, GPIO_MODE_INPUT_OUTPUT);
        _configure_pins_(d6, slot, GPIO_MODE_INPUT_OUTPUT);
        _configure_pins_(d7, slot, GPIO_MODE_INPUT_OUTPUT);
    }

    esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, slot_info->card_int, false);

    int matrix_in_cd;
    if (gpio_cd != SDMMC_SLOT_NO_CD)
    {
        ESP_LOGD(TAG, "using GPIO%d as CD pin", gpio_cd);
        esp_rom_gpio_pad_select_gpio(gpio_cd);
        gpio_set_direction(gpio_cd, GPIO_MODE_INPUT);
        matrix_in_cd = gpio_cd;
    }
    else
    {
        matrix_in_cd = GPIO_MATRIX_CONST_ZERO_INPUT;
    }
    esp_rom_gpio_connect_in_signal(matrix_in_cd, slot_info->card_detect, false);

    int matrix_in_wp;
    if (gpio_wp != SDMMC_SLOT_NO_WP)
    {
        ESP_LOGD(TAG, "using GPIO%d as WP pin", gpio_wp);
        esp_rom_gpio_pad_select_gpio(gpio_wp);
        gpio_set_direction(gpio_wp, GPIO_MODE_INPUT);
        matrix_in_wp = gpio_wp;
    }
    else
    {
        matrix_in_wp = GPIO_MATRIX_CONST_ONE_INPUT;
    }

    esp_rom_gpio_connect_in_signal(matrix_in_wp, slot_info->write_protect, true);
#if 1
    // esp_err_t ret = sdmmc_host_set_card_clk(slot, 400);
    // if (ret != ESP_OK) {
    //     ESP_LOGE(TAG, "setting probing freq and 1-bit bus failed");
    //     ESP_LOGE(TAG, "%s: sdmmc_host_set_card_clk returned 0x%x", __func__, ret);
    //     return ret;
    // }
    // sdmmc_host_set_bus_width(slot, 1);
    // ret = sdmmc_host_set_bus_width(slot, 1);
    // if (ret != ESP_OK) {
    //     return ret;
    // }
#endif
    return ESP_OK;
}
#endif

/// @brief todo
/// @param requestbuffer
/// @return
#if 1
esp_err_t zyp_handle_cmd_fream(struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer, sdmmc_card_t *card, sdmmc_command_t *cmd)
{
    ZYP_DEBUG_MMC("deubg requestbuffer->rwFlag:%d\n", requestbuffer->rwFlag);
    if (cmd == NULL)
    {
        ZYP_DEBUG_MMC("cmd varib is  NULL \n");
        return ESP_FAIL;
    }
    if (card == NULL)
    {
        ZYP_DEBUG_MMC("card varib is NULL \n");
        return ESP_FAIL;
    }

    ZYP_DEBUG_MMC(" zyp_handle_cmd_fream\n");
    esp_err_t err;
    if (requestbuffer != NULL)
    {
        // zyp_getrequetCmdID(requestbuffer, cmd);
        zyp_getrespType(requestbuffer, cmd);
        cmd->opcode = requestbuffer->cmdId;
    }

    if (requestbuffer->rwFlag == MMMC_CMD_FREAM_START_BYTE)
    {
        if (requestbuffer->cmdId == MMC_GO_IDLE_STATE && requestbuffer->endBit == MMMC_CMD_FREAM_START_BYTE)
        {
            ZYP_DEBUG_MMC("Fream ALL IS ZEAR\n");
            memset(requestbuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct RequestBuffer));
            memset(responsebuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct ResponseBuffer));
            return ESP_FAIL;
        }

        if (requestbuffer->cmdId == MMC_GO_IDLE_STATE && requestbuffer->endBit == MMMC_CMD_FREAM_END_BYTE) /// NO RESP
        {
            unsigned int cmd0_parm = LE32_TO_BE(requestbuffer->cmdParm);
            if (cmd0_parm == 0xF0F0F0F0)
            {
                err = zyp_sendNomalCmd(cmd, card, requestbuffer);
                return err;
            }

            ZYP_DEBUG_MMC("cmd0 parm:%08x\n", requestbuffer->cmdParm);
            ZYP_DEBUG_MMC("LE32_TO_BE cmd0 parm:%08x\n", LE32_TO_BE(requestbuffer->cmdParm));

            if (cmd0_parm == 0xFFFFFFFA)
            {
                uint8_t *read_buffer = (uint8_t *)heap_caps_malloc(EXT_CSD_MMC_SIZE, MALLOC_CAP_SPIRAM);
                cmd->arg = requestbuffer->cmdParm;
                cmd->data = read_buffer; /// must be null  if not  cmd send err why not vrigin flow is ok?
                cmd->blklen = EXT_CSD_MMC_SIZE;
                cmd->datalen = EXT_CSD_MMC_SIZE;
#if IS_ENABLE_MMC_FUNCTION_DEBUG
                ZYP_DEBUG_MMC("cmd->opcode:%lx,cmd->arg:%lx,cmd->flags:%x\n", cmd->opcode, cmd->arg, cmd->flags);
#endif
                // return sdmmc_send_cmd(card, cmd);
                if (zyp_sendReadCmd(cmd, card, requestbuffer, (unsigned int *)read_buffer, 0, 1) != ESP_OK)
                {
                    ZYP_DEBUG_MMC("CMD0 F ERR\n");
                    return ESP_FAIL;
                }
                return ESP_OK;
            }

            /// host set sdr 1bit fre defalut 400k               ///cmd0 no resp
            if (zyp_sendNomalCmd(cmd, card, requestbuffer))
            {
                // ZYP_DEBUG_MMC("zyp_sendNomalCmd cmd%d err\n", (unsigned int)cmd->opcode);
            }

            if (is_power_off == false && cmd0_parm == 0) /// cm0 amd 下电
            {
#if 1
                slot_config.width = BUS_WITH_1BIT;
                ZYP_SDMMC_CHECK_CMD(sdmmc_host_init_slot(card->host.slot, &slot_config), err, TAG, "host_init_slot err");
                card->host.set_bus_width(card->host.slot, BUS_WITH_1BIT);
#endif
                ZYP_SDMMC_CHECK_CMD(sdmmc_host_set_card_clk(card->host.slot, SDMMC_FREQ_PROBING), err, TAG, " switch host clk err");
                ZYP_SDMMC_CHECK_CMD(sdmmc_host_set_bus_width(card->host.slot, BUS_WITH_1BIT), err, TAG, " switch host bus err");
                ZYP_SDMMC_CHECK_CMD(sdmmc_host_set_bus_ddr_mode(card->host.slot, 0), err, TAG, " switch host ddr err");
            }

            memset(requestbuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct RequestBuffer));
            memset(responsebuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct ResponseBuffer));
            return ESP_OK;
        }

        else if (requestbuffer->cmdId == MMC_SET_RELATIVE_ADDR) /// cmd3 set goalbl card.rca and cmd9 set crad.csd  special handlding if not cmd8 err （ cmd8 judge card->csd.mmc_ver）
        {
            ZYP_DEBUG_MMC("MMC_SET_RELATIVE_ADDR\n");
            if (!zyp_sdmmc_send_cmd_set_relative_addr_handlefream(card, cmd, requestbuffer, &(card->rca)))
            {
                zyp_handle_mmc_cmd_response(cmd, requestbuffer, responsebuffer, false);
            }
            else
            {
                zyp_handle_mmc_cmd_response(cmd, requestbuffer, responsebuffer, true);
            }

            memset(requestbuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct RequestBuffer));
            memset(responsebuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct ResponseBuffer));
            return ESP_OK;
        }

        else if (requestbuffer->cmdId == MMC_SEND_CSD)
        {
            /// todo  send cmd9 the card->csd has not init ,resovle  card->csd has benn init card->csd.mmc_ver has value
            if (!zyp_sdmmc_send_cmd_send_csd_handlefream(card, cmd, requestbuffer, &card->csd))
            {
                zyp_handle_mmc_cmd_response(cmd, requestbuffer, responsebuffer, false);
            }
            else
            {
                zyp_handle_mmc_cmd_response(cmd, requestbuffer, responsebuffer, true);
            }

            memset(requestbuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct RequestBuffer));
            memset(responsebuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct ResponseBuffer));
            return ESP_OK;
        }

        else if (requestbuffer->cmdId == MMC_SEND_EXT_CSD)
        {
            zyp_sendCmd_EXT_CSD_RespData(card, cmd, requestbuffer, responsebuffer);
            memset(requestbuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct RequestBuffer));
            memset(responsebuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct ResponseBuffer));
            return ESP_OK;
        }
        /// todo  MMC_CMD_BUS_TEST_W  MMC_CMD_BUS_TEST_R   MMC_CMD_APP_CMD_2   MMC_SEND_WRITE_PROT   MMC_SEND_WRITE_PROT_TYPE

        else if (requestbuffer->cmdId == MMC_SWITCH)
        {
            ZYP_DEBUG_MMC("MMC_SWITCH\n");
            if (!zyp_sendNomalCmd(cmd, card, requestbuffer))
            {
                unsigned int cmdRes = cmd->response[MMC_PESP_RETURN_VALUE_ARRY_ZEARO];
                ZYP_DEBUG_MMC("cmdRes:%08x\n", cmdRes);
                ZYP_DEBUG_MMC("sizeof cmd.response:%d\n", sizeof(cmd->response)); // 16Byte
                for (int i = 0; i < 4; i++)
                {
                    ZYP_DEBUG_MMC("%08X\t", (unsigned int)cmd->response[i]);
                }
                ZYP_DEBUG_MMC("\n");
                zyp_wrappeRespnceCmdFrameAndSendHex(cmd, requestbuffer, responsebuffer);
            }
            else
            {
                ZYP_DEBUG_MMC("zyp_sendNomalCmd cmd%d err\n", (unsigned int)cmd->opcode);
                zyp_wrappeRespnceCmdR_W_Err_FrameAndSendHex(cmd, requestbuffer, responsebuffer);
            }

            if ((requestbuffer->cmdParm & SWITCH_HIGH_SHIFTBIT) == SWITCH_BUS_WTCH_SHIFTBIT) /// BUS_SWTICH
            {
                ZYP_DEBUG_MMC("switch bus \n");
                if (requestbuffer->cmdParm & SWITCH_DDR_SHIFTBIT)
                {
                    ZYP_DEBUG_MMC("switch ddr mode =1\n");
                    card->is_ddr = 1;
                    sdmmc_host_set_bus_ddr_mode(card->host.slot, card->is_ddr);
                }
                else
                {
                    ZYP_DEBUG_MMC("switch ddr mode =0\n");
                    card->is_ddr = 0;
                    sdmmc_host_set_bus_ddr_mode(card->host.slot, card->is_ddr);
                }

                char width[] = {BUS_WITH_1BIT, BUS_WITH_4BIT, BUS_WITH_8BIT};
#if 1
                uint8_t set_bus_width_ = width[(requestbuffer->cmdParm & BUS_WITH_SHIFTBIT) >> BUS_WITH_8BIT];
                ZYP_DEBUG_MMC("set_bus_width_ : %d, logset_bus_width:%f \n", set_bus_width_, log2(set_bus_width_));
                card->log_bus_width = (uint32_t)log2(set_bus_width_);
                slot_config.width = set_bus_width_;
                // sdmmc_host_init_slot(card->host.slot, &slot_config);
                zyp_sdmmc_host_init_config_slot(card->host.slot, &slot_config);
#endif
                sdmmc_host_set_bus_width(card->host.slot, (set_bus_width_));

                // card->host.set_bus_width(card->host.slot, (width[(requestbuffer->cmdParm & BUS_WITH_SHIFTBIT) >> BUS_WITH_8BIT])); ///??? todo change physical bus width   why sdmmc_host_get_slot_width get bus alwy 1？
                ZYP_DEBUG_MMC("get_log_bus_width : %d\n", card->log_bus_width);
            }

            uint32_t cmdParms[] = {SWITCH_HIGH_SPEED, SWITCH_HS200, SWITCH_HS400}; /// HS
            uint32_t ddrModes[] = {0, 0, 1};
            uint32_t clocks[] = {SDMMC_FREQ_HIGHSPEED, 0, 0};
            for (size_t i = 0; i < sizeof(cmdParms) / sizeof(cmdParms[0]); i++)
            {
                if (requestbuffer->cmdParm == cmdParms[i])
                {
                    card->is_ddr = ddrModes[i];
                    sdmmc_host_set_bus_ddr_mode(card->host.slot, card->is_ddr);
                    sdmmc_host_set_card_clk(card->host.slot, ((clocks[i] == 0) ? SDMMC_FREQ_HIGHSPEED : clocks[i]));
                    break;
                }
                else
                {
                    if (i == sizeof(cmdParms) / sizeof(cmdParms[0]) - 1)
                    {
                        ZYP_DEBUG_MMC(" not switch hs mode hs200 hs400\n");
                    }
                }
            }
            memset(requestbuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct RequestBuffer));
            memset(responsebuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct ResponseBuffer));
            return ESP_OK;
        }

        else if (requestbuffer->cmdId == SEND_WRITE_PROT_TYPE || requestbuffer->cmdId == MMC_SEND_WRITE_PROT)
        {
            size_t read_size = 0;
            cmd->opcode = requestbuffer->cmdId;
            // if (requestbuffer->cmdId == MMC_SEND_WRITE_PROT)
            // {
            //     read_byte = 4;
            // }
            // if (requestbuffer->cmdId == SEND_WRITE_PROT_TYPE)
            // {
            //     read_byte = 8;
            // }
            // card->host.slot = 1;
            read_size = EXT_CSD_MMC_SIZE;
            uint8_t *read_bufer = (uint8_t *)heap_caps_malloc(EXT_CSD_MMC_SIZE, MALLOC_CAP_DMA); /// DMa  with psram flags can not use
            memset(read_bufer, 0, EXT_CSD_MMC_SIZE);
            ZYP_DEBUG_MMC("-----------cmd %d -----------\n", requestbuffer->cmdId);
            // err = zyp_mmc_hanlde_write_protect_or_type(cmd, card, requestbuffer, responsebuffer, buffer_r, read_size);
            cmd->opcode = requestbuffer->cmdId;
            cmd->flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_CMD_READ;
            cmd->blklen = EXT_CSD_MMC_SIZE;
            cmd->datalen = 512;
            cmd->data = read_bufer;
            cmd->timeout_ms = SDMMC_WRITE_CMD_TIMEOUT_MS;
            cmd->arg = requestbuffer->cmdParm;
            cmd->no_need_auto_stop = 0;
            err = sdmmc_send_cmd(card, cmd);
            // if (!err)
            // {
            ZYP_DEBUG_MMC("err:%s\n", esp_err_to_name(err));
            zyp_wrappeRespnceCmdFrameAndSendHex(cmd, requestbuffer, responsebuffer);
            zyp_wrappeRespnceDataFrameAndSendHex_nostruct(requestbuffer, (char *)read_bufer, read_size);
            // }
            // else
            // {
            //     zyp_handle_mmc_cmd_response(cmd, requestbuffer, responsebuffer, true);
            // }

            if (read_bufer != NULL)
            {
                heap_caps_free(read_bufer);
            }
            read_size = 0;
            memset(requestbuffer, 0, sizeof(struct RequestBuffer));
            memset(responsebuffer, 0, sizeof(struct ResponseBuffer));
        }

        // else if (zyp_judge_is_nomal_cmd(cmd))
        else
        {
            if (!zyp_sendNomalCmd(cmd, card, requestbuffer))
            {
                unsigned int cmdRes = cmd->response[MMC_PESP_RETURN_VALUE_ARRY_ZEARO];
                ZYP_DEBUG_MMC("cmdRes:%08x\n", cmdRes);
                ZYP_DEBUG_MMC("sizeof cmd.response:%d\n", sizeof(cmd->response)); // 16Byte
                for (int i = 0; i < 4; i++)
                {
                    ZYP_DEBUG_MMC("%08X\t", (unsigned int)cmd->response[i]);
                }
                ZYP_DEBUG_MMC("\n");
                zyp_wrappeRespnceCmdFrameAndSendHex(cmd, requestbuffer, responsebuffer);
            }

            else
            {
                ZYP_DEBUG_MMC("zyp_sendNomalCmd Send cmd%d err\n", (unsigned int)cmd->opcode);
                zyp_wrappeRespnceCmdR_W_Err_FrameAndSendHex(cmd, requestbuffer, responsebuffer);
            }
            memset(requestbuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct RequestBuffer));
            memset(responsebuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct ResponseBuffer));
            return ESP_OK;
        }
    }

    else if (requestbuffer->rwFlag == MMC_CMD_DEBUG_FLAG)
    {
        if (requestbuffer->cmdId == MMC_SEND_OP_COND) /// scirpt mode  cmd1
        {
            ZYP_DEBUG_MMC("MMC_SEND_OP_COND script mode\n");
            for (size_t i = 0; i < SEND_OP_COND_MAX_ENTRY; i++)
            {
                vTaskDelay(pdMS_TO_TICKS(50));
                if (!zyp_sendNomalCmd(cmd, card, requestbuffer))
                {
                    ZYP_DEBUG_MMC("cmdRes:%08x\n", (unsigned int)cmd->response[MMC_PESP_RETURN_VALUE_ARRY_ZEARO]);
                    if (cmd->response[MMC_PESP_RETURN_VALUE_ARRY_ZEARO] == SEND_OP_COND_READY)
                    {
                        ZYP_DEBUG_MMC("sizeof cmd.response:%d\n", sizeof(cmd->response)); // 16Byte
                        for (int i = 0; i < 4; i++)
                        {
                            ZYP_DEBUG_MMC("%08X\t", (unsigned int)cmd->response[i]);
                        }
                        ZYP_DEBUG_MMC("\n");
                        zyp_wrappeRespnceCmdFrameAndSendHex(cmd, requestbuffer, responsebuffer);
                        return ESP_OK;
                    }
                    // zyp_wrappeRespnceCmdFrameAndSendHex(cmd, requestbuffer, responsebuffer);
                }
            }
            memset(requestbuffer, 0, sizeof(struct RequestBuffer));
            memset(responsebuffer, 0, sizeof(struct ResponseBuffer));
        }

        if (requestbuffer->cmdId == MMC_CMD_APP_CMD_2)
        {
            esp_err_t err;
            unsigned int func = requestbuffer->cmdParm;
            switch (func)
            {
            case 0:
                if (!zyp_sendCmd56W(cmd, card, requestbuffer, &rwRecivebuffer, 1))
                {
                    zyp_handle_mmc_cmd_response(cmd, requestbuffer, responsebuffer, false);
                }
                else
                {
                    zyp_handle_mmc_cmd_response(cmd, requestbuffer, responsebuffer, true);
                }
                memset(cmd_data, 0, data_cmd_cnt * EXT_CSD_MMC_SIZE); ///  rwRecivebuffer->data  point to cmd_data
                // if (cmd_data != NULL)
                // {
                //     free(cmd_data);
                //     cmd_data = NULL;
                // }
                // rwRecivebuffer.data = NULL;

                if (rwRecivebuffer.data)
                {
                    free(rwRecivebuffer.data);
                    rwRecivebuffer.data = NULL;
                }
                cmd_data = NULL;

                data_cmd_cnt = 0;
                totall_bytes_received_data = 0;
                usb_data_send_flag = false;
                memset(requestbuffer, 0, sizeof(struct RequestBuffer));
                memset(responsebuffer, 0, sizeof(struct ResponseBuffer));
                break;
            case 1:
                zyp_sendCmd56R(cmd, card, requestbuffer, responsebuffer, requestbuffer->cmdParm, readMultipeCount);
                readMultipeCount = 1;
                break;
            }
        }

        if (requestbuffer->cmdId == MMC_POWER_SET)
        {
            ZYP_DEBUG_MMC("requestbuffer->cmdParm:%0x\n", requestbuffer->cmdParm);
            EMMC_GPIO_init(GPIO_NUM_21);
            vTaskDelay(100);
            EMMC_POWER_SET(GPIO_NUM_21, requestbuffer->cmdParm);

            if (requestbuffer->cmdParm == 0)
            {
                /// emmc all pin set output and input with open-drain mode
                for (int i = 0; i < sizeof(emmc_gpio_pin_) / sizeof(emmc_gpio_pin_[0]); i++)
                {
                    EMMC_GPIO_init(emmc_gpio_pin_[i]);
                }
                vTaskDelay(pdMS_TO_TICKS(1));
                is_power_off = true;
            }
            else if (requestbuffer->cmdParm == 1)
            {
                ZYP_DEBUG_MMC("emmc power on \n");
#if 1
                slot_config.width = BUS_WITH_1BIT;
                ZYP_SDMMC_CHECK_CMD(sdmmc_host_init_slot(card->host.slot, &slot_config), err, TAG, "host_init_slot err");
                card->host.set_bus_width(card->host.slot, BUS_WITH_1BIT);
                is_power_off = false;
#endif
            }

            memset(requestbuffer, 0, sizeof(struct RequestBuffer));
            memset(responsebuffer, 0, sizeof(struct ResponseBuffer));
            return ESP_OK;
        }
        else if (requestbuffer->cmdId == ESP_POWER_SET)
        {
            esp_restart();
        }
        else if (requestbuffer->cmdId == Hard_Reset_N)
        {
            ZYP_DEBUG_MMC("Hard_Reset_N\n");
            emmc_rst_pin_init();
            vTaskDelay(pdMS_TO_TICKS(1000));
            emmc_hardware_reset();

            /// reset host  bus freq
#if 1
            slot_config.width = BUS_WITH_1BIT;
            ZYP_SDMMC_CHECK_CMD(sdmmc_host_init_slot(card->host.slot, &slot_config), err, TAG, "host_init_slot err");
            card->host.set_bus_width(card->host.slot, BUS_WITH_1BIT);
#endif
            ZYP_SDMMC_CHECK_CMD(sdmmc_host_set_card_clk(card->host.slot, SDMMC_FREQ_PROBING), err, TAG, " switch host clk err");
            ZYP_SDMMC_CHECK_CMD(sdmmc_host_set_bus_width(card->host.slot, BUS_WITH_1BIT), err, TAG, " switch host bus err");
            ZYP_SDMMC_CHECK_CMD(sdmmc_host_set_bus_ddr_mode(card->host.slot, 0), err, TAG, " switch host ddr err");
        }
        return ESP_OK;
    }

    else if (requestbuffer->rwFlag == MMC_CMD_READ_RWFLAGE)
    {
        if (requestbuffer->cmdId == MMC_SET_BLOCKLEN)
        {
            if (!zyp_mmc_set_blocklen_cmd_fream(card, cmd, requestbuffer))
            {
                zyp_wrappeRespnceCmdFrameAndSendHex(cmd, requestbuffer, responsebuffer);
            }
            else
            {
                ZYP_DEBUG_MMC("setBlockLenCmd err\n");
            }
        }
        else if (requestbuffer->cmdId == MMC_SET_BLOCK_COUNT)
        {
            readMultipeCount = zyp_setBlockCountCmd(cmd, card, requestbuffer);
            // writeToallmultipeCount_Byte = mmc->write_bl_len * writeMultipeCount;
            ZYP_DEBUG_MMC("readMultipeCount:%d\n", readMultipeCount); /// todo can compare to next cmddata fream cnt can optimize
            zyp_wrappeRespnceCmdFrameAndSendHex(cmd, requestbuffer, responsebuffer);
            memset(requestbuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct RequestBuffer));
            memset(responsebuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct ResponseBuffer));
        }

        else if (requestbuffer->cmdId == MMC_READ_BLOCK_SINGLE || requestbuffer->cmdId == MMC_READ_BLOCK_MULTIPLE)
        {
            unsigned int *sendReadDataCmdbuffer = (unsigned int *)heap_caps_malloc(readMultipeCount * EXT_CSD_MMC_SIZE, MALLOC_CAP_DMA);
            memset(sendReadDataCmdbuffer, 0, readMultipeCount * EXT_CSD_MMC_SIZE);
            ZYP_DEBUG_MMC("read cmd parm readMultipeCount: %d, fream cnt(read start addr): %d\n", readMultipeCount, requestbuffer->cmdParm);
            if (requestbuffer->requestDirection == 0x01) /// defiend end
            {
                cmd->no_need_auto_stop = 1;
            }
            err = zyp_sendReadCmd(cmd, card, requestbuffer, sendReadDataCmdbuffer, requestbuffer->cmdParm, readMultipeCount); // Just don't rely  cmd23 after writeToallmultipeCount_Byte
            ZYP_DEBUG_MMC("err:%s\n", esp_err_to_name(err));
            if (!err)
            {
                zyp_wrappeRespnceCmdFrameAndSendHex(cmd, requestbuffer, responsebuffer);
                zyp_wrappeRespnceDataFrameAndSendHex_nostruct(requestbuffer, (char *)sendReadDataCmdbuffer, readMultipeCount * EXT_CSD_MMC_SIZE);
            }
            else
            {
                zyp_handle_mmc_cmd_response(cmd, requestbuffer, responsebuffer, true);
            }

            if (sendReadDataCmdbuffer != NULL)
            {
                free(sendReadDataCmdbuffer); /// assert failed: block_trim_free tlsf.c:504 (block_is_free(block) && "block must be free")  or no free     heapmalloc just noly 100KB  set cmd_data golbal. just be similar to xu4 fream
                sendReadDataCmdbuffer = NULL;
            }
            cmd->no_need_auto_stop = 0;
            memset(requestbuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct RequestBuffer));
            memset(responsebuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct ResponseBuffer));
            readMultipeCount = 1;
        }
    }

    else if (requestbuffer->rwFlag == MMC_CMD_WRITE_RWFLAGE)
    {
        ZYP_DEBUG_MMC("cmd.cmdId:%d\n", (unsigned int)cmd->opcode);
        if (requestbuffer->cmdId == MMC_SET_BLOCKLEN)
        { /// There's a problem with writing this way. The resp of cmd is all 0. You didn't pass it in as a parameter, did you????????
            if (!zyp_mmc_set_blocklen_cmd_fream(card, cmd, requestbuffer))
            {
                zyp_wrappeRespnceCmdFrameAndSendHex(cmd, requestbuffer, responsebuffer);
            }
            else
            {
                ZYP_DEBUG_MMC("setBlockLenCmd err\n");
            }
            memset(requestbuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct RequestBuffer));
            memset(responsebuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct ResponseBuffer));
        }

        /// if here  just set package write?
        else if (requestbuffer->cmdId == MMC_SET_BLOCK_COUNT)
        {
            writeMultipeCount = zyp_setBlockCountCmd(cmd, card, requestbuffer);
            // writeToallmultipeCount_Byte = mmc->write_bl_len * writeMultipeCount;
            ZYP_DEBUG_MMC("no real send cmd23 multipeCount:%d\n", writeMultipeCount); /// todo can compare to next cmddata fream cnt can optimize
            zyp_wrappeRespnceCmdFrameAndSendHex(cmd, requestbuffer, responsebuffer);
            memset(requestbuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct RequestBuffer));
            memset(responsebuffer, MMC_REQUST_AND_RESP_DEFALUT_VALUE, sizeof(struct ResponseBuffer));
        }

        else if (requestbuffer->cmdId == MMC_WRITE_BLOCK_SINGLE || requestbuffer->cmdId == MMC_WRITE_BLOCK_MULTIPLE) /// cmd23 resp is cmd23 cmd25 resp is cmd13
        {
            ZYP_DEBUG_MMC("write cmd parm writeMultipeCount:%d, fream cnt(write start addr): %d \n", writeMultipeCount, requestbuffer->cmdParm);
            ZYP_DEBUG_MMC("data_cmd_cnt:%d\n", data_cmd_cnt);
            ZYP_DEBUG_MMC("totall_bytes_received_data:%d\n", totall_bytes_received_data);
            // err = zyp_sendWriteCmd(cmd, card, requestbuffer, &rwRecivebuffer, data_cmd_cnt); // Just don't rely  cmd23 after writeToallmultipeCount_Byte
            if (requestbuffer->requestDirection == 0x00) /// open end
            {
                cmd->flags = SCF_CMD_ADTC | SCF_RSP_R1; /// auto stop  0x3000
            }
            else if (requestbuffer->requestDirection == 0x01) /// define end
            {
                cmd->opcode = requestbuffer->cmdId;
                cmd->arg = requestbuffer->cmdParm;
                cmd->blklen = EXT_CSD_MMC_SIZE;
                cmd->datalen = writeMultipeCount * EXT_CSD_MMC_SIZE;
                cmd->flags = SCF_CMD_ADTC | SCF_RSP_R1;
                cmd->no_need_auto_stop = 1;
                // cmd->data = (void *)rwRecivebuffer.data;   buffer 0x3c069b50 can not be used for DMA[0m  !!!!!
                cmd->timeout_ms = SDMMC_WRITE_CMD_TIMEOUT_MS;
            }
            err = zyp_sendWriteCmd(cmd, card, requestbuffer, &rwRecivebuffer, writeMultipeCount);
            ZYP_DEBUG_MMC("err:%s\n", esp_err_to_name(err));
            if (!err)
            {
                zyp_handle_mmc_cmd_response(cmd, requestbuffer, responsebuffer, false);
            }
            else
            {
                zyp_handle_mmc_cmd_response(cmd, requestbuffer, responsebuffer, true);
            }
            /// for next time recive
            // free(rwRecivebuffer.data); /// atrully free cmd_data ?  rwRecivebuffer.data just ponter
            cmd->no_need_auto_stop = 0;
            memset(cmd_data, 0, data_cmd_cnt * EXT_CSD_MMC_SIZE); ///  rwRecivebuffer->data  point to cmd_data
            ZYP_DEBUG_DATA("\n-------------- cmd send after rwRecivebuffer->data value:--------------\n");
            /// 将 rwRecivebuffer->data
            char *data1 = (char *)rwRecivebuffer.data;
            for (size_t i = 0; i < data_cmd_cnt * EXT_CSD_MMC_SIZE; i++)
            {
                ZYP_DEBUG_DATA("%02X ", data1[i]);
            }
            ZYP_DEBUG_MMC("\n"); /// free cmd_data actully free rwRecivebuffer->data   free rwRecivebuffer->data actully free cmd_data ?

            // if (cmd_data != NULL)
            // {
            //     free(cmd_data); /// assert failed: block_trim_free tlsf.c:504 (block_is_free(block) && "block must be free")  or no free     heapmalloc just noly 100KB  set cmd_data golbal. just be similar to xu4 fream
            //     cmd_data = NULL;
            // }
            // rwRecivebuffer.data = NULL;
            writeMultipeCount = 1;
            if (rwRecivebuffer.data) /// rwRecivebuffer.data and  cmd_data  are point same memory ,and free cmd_data just free rwRecivebuffer.data,just free once，after  rwRecivebuffer.data  and cmd_data must point null
            {
                ZYP_DEBUG_MMC("have free rwRecivebuffer.data\n");
                heap_caps_free(rwRecivebuffer.data);
                rwRecivebuffer.data = NULL;
                cmd_data = NULL;
            }
            data_cmd_cnt = 0;
            totall_bytes_received_data = 0;
            usb_data_send_flag = false;
        }
    }

    else if (requestbuffer->rwFlag == MMC_CMD_Vrify_YX3126) /// request rwflag 03
    {
        ///
        ZYP_DEBUG("requestbuffer->cmdParm:0X%02X\n", requestbuffer->cmdParm);
        switch (requestbuffer->cmdId)
        {
        case 0:
            zyp_init_mmc_random(card); /// VCMDID 00  MMC init
            zyp_sdmmc_configure_bus_fre_mode(card, SDMMC_FREQ_PROBING, 1, 0);
            break;
        case 1: /// VCMDID 01   pacekd cmd write
            zyp_mmc_packed_write(cmd, card, requestbuffer, responsebuffer, address_w, block_counts_w, sizeof(address_w) / sizeof(address_w[0]), &write_data[0]);
            break;
        case 2: /// VCMDID 02 pacekd cmd read
            zyp_mmc_packed_read(cmd, card, requestbuffer, responsebuffer, address_w, block_counts_w, sizeof(address_w) / sizeof(address_w[0]));
            break;
        case 3:
            zyp_mmc_create_cmdq_task_write(cmd, card, requestbuffer, responsebuffer, taskId[0], number_block[1], lba[0]); /// VCMDID 03  cmdq write
            ZYP_DEBUG("write watting task1\n");
            vTaskDelay(pdMS_TO_TICKS(500));
            zyp_mmc_create_cmdq_task_write(cmd, card, requestbuffer, responsebuffer, taskId[1], number_block[10], lba[1]);
            break;
        case 4: /// VCMDID 04   cmdq read
            zyp_mmc_create_cmdq_task_read(cmd, card, requestbuffer, responsebuffer, taskId[2], number_block[1], lba[0]);
            break;
        case 5:
            MMC_LOCK_T *lock_p = (MMC_LOCK_T *)heap_caps_malloc(sizeof(MMC_LOCK_T), MALLOC_CAP_DMA);
            lock_p->mode = 5; /// lock   set_pwd
            // lock_p->mode = 1; /// unlock set_pwd
            lock_p->len = 1;
            lock_p->pwd = 1;
            zyp_mmc_lock_unlock(cmd, card, requestbuffer, responsebuffer, lock_p, sizeof(MMC_LOCK_T));
            if (lock_p != NULL)
            {
                free(lock_p);
                lock_p = NULL;
            }
            break;
        case 6:
            MMC_LOCK_T *unlock_p = (MMC_LOCK_T *)heap_caps_malloc(sizeof(MMC_LOCK_T), MALLOC_CAP_DMA);

            unlock_p->mode = 2; /// 0 unlock     password not clear  (means  after power on is lock )
            // unlock_p->mode = 6; /// 0 unlock  password  clear    (means  power on is unlock )
            unlock_p->len = 1;
            unlock_p->pwd = 1;
            zyp_mmc_lock_unlock(cmd, card, requestbuffer, responsebuffer, unlock_p, sizeof(MMC_LOCK_T));
            if (unlock_p != NULL)
            {
                free(unlock_p);
                unlock_p = NULL;
            }
/// first unclok then clean password
#if 0
            unlock_p->mode = 0;              ///unlock  not clean password
            unlock_p->len = 1;
            unlock_p->pwd = 1;
            zyp_mmc_lock_unlock(cmd, card, requestbuffer, responsebuffer, unlock_p, sizeof(MMC_LOCK_T));

            unlock_p->mode = 2;              ///unlock  clean password
            unlock_p->len = 1;
            unlock_p->pwd = 1;
            zyp_mmc_lock_unlock(cmd, card, requestbuffer, responsebuffer, unlock_p, sizeof(MMC_LOCK_T));
            if (unlock_p != NULL)
            {
                free(unlock_p);
            }
#endif
            break;
        case 7:
            MMC_FORCE_CLEAN_T *clean = heap_caps_malloc(sizeof(MMC_FORCE_CLEAN_T), MALLOC_CAP_DMA);
            clean->mode = 8;
            zyp_mmc_clear_emmc(cmd, card, requestbuffer, responsebuffer, clean, sizeof(MMC_FORCE_CLEAN_T));
            if (clean != NULL)
            {
                free(clean);
            }
            break;
        case 8: /// boot1 add PERM_WP differ case test verifty
            zyp_boot1_add_perm_wp(cmd, card, requestbuffer, responsebuffer);
            // zyp_mmc_old_erase_group();
            break;
        case 9:
            zyp_write_X_partion_1MB(cmd, card, requestbuffer, responsebuffer);
            break;
        case 10:
            zyp_read_cid(card);
            break;
        case 11:
            ZYP_DEBUG("FFU MODE\n");
            uint8_t *ext_csd_buffer = (uint8_t *)heap_caps_malloc(sizeof(uint8_t) * EXT_CSD_MMC_SIZE, MALLOC_CAP_8BIT);
            if (!ext_csd_buffer)
            {
                ZYP_DEBUG_MMC("malloc ext_csd_buffer err\n");
            }
            switch (requestbuffer->cmdParm)
            {
            case FFU_POWER_MODE:
                ZYP_DEBUG("FFU FFU_POWERs_MODE\n");
                zyp_ffu_download_powercycle(cmd, card, requestbuffer, responsebuffer);
                break;
            case FFU_CMD0_MODE:
                ZYP_DEBUG("FFU FFU_CMD0_MODE\n");
                zyp_ffu_download_cmd0(cmd, card, requestbuffer, responsebuffer, ext_csd_buffer);
                break;
            case FFU_HARDRESET_MODE:
                ZYP_DEBUG("FFU FFU_HARDRESET_MODE\n");
                zyp_ffu_download_hardreset(cmd, card, requestbuffer, responsebuffer, ext_csd_buffer);
                break;
            case FFU_SMI_WRITE_RANDOME_DATA_MODE:
                ZYP_DEBUG("FFU FFU_SMI_WRITE_RANDOME_DATA_MODE\n");
                zyp_ffu_download_random_write(cmd, card, requestbuffer, responsebuffer, ext_csd_buffer);
                break;
            case FFU_CMD25_PARME_ERR_MODE:
                ZYP_DEBUG("FFU FFU_CMD25_PARME_ERR_MODE\n");
                zyp_ffu_download_cmd25_parm_err(cmd, card, requestbuffer, responsebuffer, ext_csd_buffer);
                break;
            default:
                break;
            }
            // zyp_ffu_download_smi(cmd, card, requestbuffer, responsebuffer);
            if (ext_csd_buffer != NULL)
            {
                heap_caps_free(ext_csd_buffer);
            }
            break;
        case 12:
            // zyp_ffu_download_yx3126(cmd, card, requestbuffer, responsebuffer);
            break;
        default:
            break;
        }
    }

    else if (requestbuffer->rwFlag == MMC_CMD_BUS_TEST_FLAG)
    {
        if (requestbuffer->cmdId == MMC_CMD_BUS_TEST_W)
        {
            ZYP_DEBUG_USB("MMC_CMD_BUS_TEST_W\n");
            zyp_sendCmd19AndRespFrame(cmd, card, requestbuffer, responsebuffer);
            zyp_handle_mmc_cmd_response(cmd, requestbuffer, responsebuffer, false);
#if 0
            if (!zyp_sendCmd19AndRespFrame(cmd, card, requestbuffer, responsebuffer))
            {
                zyp_handle_mmc_cmd_response(cmd, requestbuffer, responsebuffer, false);
            }
            else
            {
                zyp_handle_mmc_cmd_response(cmd, requestbuffer, responsebuffer, true);
            }
#endif
            // if (cmd_data != NULL)
            // {
            //     free(cmd_data);
            //     cmd_data = NULL;
            // }
            // rwRecivebuffer.data = NULL;

            if (rwRecivebuffer.data)
            {
                heap_caps_free(rwRecivebuffer.data);
                rwRecivebuffer.data = NULL;
            }
            cmd_data = NULL;

            data_cmd_cnt = 0;
            memset(requestbuffer, 0, sizeof(struct RequestBuffer));
            memset(responsebuffer, 0, sizeof(struct ResponseBuffer));
            memset(&rwRecivebuffer, 0, sizeof(struct RwReciveBuffer));
            return ESP_OK;
        }

        else if (requestbuffer->cmdId == MMC_CMD_BUS_TEST_R)
        {
            ZYP_DEBUG_MMC("BUS_TEST_R begain\n");
            ZYP_DEBUG_MMC("BUS_TEST_R err %s\n", esp_err_to_name(zyp_sendCmd14AndRespFrame(cmd, card, requestbuffer, responsebuffer)));
            memset(requestbuffer, 0, sizeof(struct RequestBuffer));
            memset(responsebuffer, 0, sizeof(struct ResponseBuffer));
            ZYP_DEBUG_USB("BUS_TEST_R end\n");
            return ESP_OK;
        }
    }

    else if (requestbuffer->rwFlag == MMC_CMD_PROGRAM_CID_CSD_FLAG)
    {
        ZYP_DEBUG_USB("MMC_CMD_PROGRAM_CID_CSD_FLAG\n");
        if (requestbuffer->cmdId == MMC_PROGRAM_CID || requestbuffer->cmdId == MMC_PROGRAM_CSD)
        {
            zyp_sendCmdPro_CIDOrCSD_RespCmdFrame(cmd, card, requestbuffer, responsebuffer, &rwRecivebuffer);
            // if (cmd_data != NULL)
            // {
            //     free(cmd_data);
            //     cmd_data = NULL;
            // }
            // rwRecivebuffer.data = NULL;

            if (rwRecivebuffer.data)
            {
                heap_caps_free(rwRecivebuffer.data);
                rwRecivebuffer.data = NULL;
            }
            cmd_data = NULL;
            // data_cmd_cnt=0;
            memset(requestbuffer, 0, sizeof(struct RequestBuffer));
            memset(responsebuffer, 0, sizeof(struct ResponseBuffer));
            memset(&rwRecivebuffer, 0, sizeof(struct RwReciveBuffer));
        }
    }

    return ESP_OK;
}

#endif

static esp_err_t zyp_init_sdmmc_host(int slot, const void *slot_config, int *out_slot)
{
    *out_slot = slot;
    return sdmmc_host_init_slot(slot, (const sdmmc_slot_config_t *)slot_config);
}

esp_err_t zyp_sdmmc_card_init(const sdmmc_host_t *config, sdmmc_card_t *card)
{
    memset(card, 0, sizeof(*card));
    memcpy(&card->host, config, sizeof(*config));
    const bool is_spi = host_is_spi(card);
    const bool always = true;
    const bool io_supported = true;

    /* Check if host flags are compatible with slot configuration. */
    ZYP_SDMMC_INIT_FUN_STEP(!is_spi, sdmmc_fix_host_flags);

    /* Reset SDIO (CMD52, RES) before re-initializing IO (CMD5). */ /// SDcmd52
    // ZYP_SDMMC_INIT_FUN_STEP(io_supported, sdmmc_io_reset);

    /* GO_IDLE_STATE (CMD0) command resets the card */
    ZYP_SDMMC_INIT_FUN_STEP(always, sdmmc_send_cmd_go_idle_state); /// cmd0

    /* SEND_IF_COND (CMD8) command is used to identify SDHC/SDXC cards. */ /// SDcmd8 check  OCR
    // ZYP_SDMMC_INIT_FUN_STEP(always, sdmmc_init_sd_if_cond);

    /* IO_SEND_OP_COND(CMD5), Determine if the card is an IO card. */
    ZYP_SDMMC_INIT_FUN_STEP(io_supported, sdmmc_init_io); /// SD IOCMD5   不发监测不到是sd还是emmc？

    const bool is_mem = card->is_mem;
    const bool is_sdio = !is_mem;

    /* Enable CRC16 checks for data transfers in SPI mode */
    // ZYP_SDMMC_INIT_FUN_STEP(is_spi, sdmmc_init_spi_crc);             ///sd cmd59

    /* Use SEND_OP_COND to set up card OCR */
    ZYP_SDMMC_INIT_FUN_STEP(is_mem, sdmmc_init_ocr); /// cheack mmc or sd mode is sd send cmd41   is emmc send cmd1

    const bool is_mmc = is_mem && card->is_mmc;
    const bool is_sdmem = is_mem && !is_mmc;

    ESP_LOGD(TAG, "%s: card type is %s", __func__,
             is_sdio ? "SDIO" : is_mmc ? "MMC"
                                       : "SD");

    /* Read the contents of CID register*/
    ZYP_SDMMC_INIT_FUN_STEP(is_mem, sdmmc_init_cid); /// CMD2

    /* Assign RCA */
    ZYP_SDMMC_INIT_FUN_STEP(!is_spi, sdmmc_init_rca); /// CMD3

    /* Read and decode the contents of CSD register */
    ZYP_SDMMC_INIT_FUN_STEP(is_mem, sdmmc_init_csd); /// MMC CMD9 SEND_CSD

    /* Decode the contents of mmc CID register */
    ZYP_SDMMC_INIT_FUN_STEP(is_mmc && !is_spi, sdmmc_init_mmc_decode_cid);

    /* Switch the card from stand-by mode to data transfer mode (not needed if
     * SPI interface is used). This is needed to issue SET_BLOCKLEN and
     * SEND_SCR commands.
     */
    ZYP_SDMMC_INIT_FUN_STEP(!is_spi, sdmmc_init_select_card); /// MMC CMD7

    /* SD memory cards:                                                   /// SD card only can action
     * Set block len for SDSC cards to 512 bytes (same as SDHC)
     * Read SCR
     * Wait to enter data transfer state
     */
    ZYP_SDMMC_INIT_FUN_STEP(is_sdmem, sdmmc_init_sd_blocklen);        /// CMD16
    ZYP_SDMMC_INIT_FUN_STEP(is_sdmem, sdmmc_init_sd_scr);             /// SDCMD
    ZYP_SDMMC_INIT_FUN_STEP(is_sdmem, sdmmc_init_sd_wait_data_ready); /// CMD13

    /* MMC cards: read CXD */
    ZYP_SDMMC_INIT_FUN_STEP(is_mmc, sdmmc_init_mmc_read_ext_csd);

    /* Try to switch card!!!!1 to HS mode if the card supports it.        ///切换为最大频率 200MHZ
     * Set card->max_freq_khz value accordingly.
     */
    ZYP_SDMMC_INIT_FUN_STEP(always, sdmmc_init_card_hs_mode);

    /* Set bus width. One call for every kind of card, then one for the host */
    if (!is_spi)
    {
        ZYP_SDMMC_INIT_FUN_STEP(is_sdmem, sdmmc_init_sd_bus_width); /// 根据当前crad的信息  send CMD6
        ZYP_SDMMC_INIT_FUN_STEP(is_sdio, sdmmc_init_io_bus_width);  /// CMD52
        ZYP_SDMMC_INIT_FUN_STEP(is_mmc, sdmmc_init_mmc_bus_width);
        ZYP_SDMMC_INIT_FUN_STEP(always, sdmmc_init_host_bus_width);
    }

    /* SD card: read SD Status register */
    ZYP_SDMMC_INIT_FUN_STEP(is_sdmem, sdmmc_init_sd_ssr);

    /* Switch to the host!!!! to use card->max_freq_khz frequency. */
    ZYP_SDMMC_INIT_FUN_STEP(always, sdmmc_init_host_frequency);

    /* Sanity check after switching the bus mode and frequency */
    ZYP_SDMMC_INIT_FUN_STEP(is_sdmem, sdmmc_check_scr);
    /* Sanity check after eMMC switch to HS mode */
    ZYP_SDMMC_INIT_FUN_STEP(is_mmc, sdmmc_init_mmc_check_ext_csd);
    /* TODO: add similar checks for SDIO */

    return ESP_OK;
}

// esp_err_t zyp_host_initialize_only(const sdmmc_host_t *host_config, const void *slot_config, sdmmc_card_t **out_card)
esp_err_t zyp_host_initialize_only(const sdmmc_host_t *host_config, const void *slot_config,
                                   sdmmc_card_t **card, sdmmc_command_t **cmd)
{
    esp_err_t err;
    // sdmmc_card_t *card = NULL;
    //  &requestbuffer= (struct RequestBuffer *)malloc(sizeof(struct RequestBuffer));
    *cmd = (sdmmc_command_t *)malloc(sizeof(sdmmc_command_t));
    if (*cmd == NULL)
    {
        ZYP_DEBUG_MMC("Failed to allocate memory for sdmmc_command_t");
    }
    ZYP_DEBUG_MMC("addr cmd = %p\n", *cmd);
    // 1. allcoate card structure menory
    *card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t));
    ZYP_DEBUG_MMC("addr card = %p\n", *card);
    if (*card == NULL)
    {
        ZYP_DEBUG_MMC("Failed to allocate memory for sdmmc_card_t");
    }

    // memset(card, 0, sizeof(*card));
    // 2. init host contrller                            ///will call back function sdmmc_host_init
    err = (*host_config->init)();
    if (err != ESP_OK)
    {
        ZYP_DEBUG_MMC(TAG, "Host init failed");
        goto fail;
    }

    // 3. init gpio  slot_config pin
    err = zyp_init_sdmmc_host(host_config->slot, slot_config, &(*card)->host.slot);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_MMC("Slot init failed\n");
        goto deinit_host;
    }
#if 1
    // 4. detect  eMMC
    err = zyp_detect_emmc(host_config, *card);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_MMC("sdmmc_card_init failed\n");
        goto deinit_slot;
    }
#endif
    // if (out_card)
    // {
    //     *out_card = card;
    // }
    return ESP_OK;
deinit_slot:
    // 如果有插槽 deinit 函数，则调用
    if (host_config->flags & SDMMC_HOST_FLAG_DEINIT_ARG)
    {
        host_config->deinit_p(host_config->slot);
    }
    else
    {
        host_config->deinit();
    }
deinit_host:
    free(*card);

fail:
    return err;
}

esp_err_t zyp_detect_emmc(const sdmmc_host_t *config, sdmmc_card_t *card)
{
    memset(card, 0, sizeof(*card));
    memcpy(&card->host, config, sizeof(*config));
    const bool is_spi = host_is_spi(card);
    const bool always = true;
    const bool io_supported = true;
    /* Check if host flags are compatible with slot configuration. */
    ZYP_SDMMC_INIT_FUN_STEP(!is_spi, sdmmc_fix_host_flags);

    const bool is_mem = card->is_mem;
    const bool is_sdio = !is_mem;

    /* Set bus width. One call for every kind of card, then one for the host */
    if (!is_spi)
    {
        ZYP_SDMMC_INIT_FUN_STEP(always, sdmmc_init_host_bus_width);
    }
    /* Sanity check after switching the bus mode and frequency */
    // ZYP_SDMMC_INIT_FUN_STEP(is_sdmem, sdmmc_check_scr);
    return ESP_OK;
}

esp_err_t zyp_host_emmc_initialize_only(const sdmmc_host_t *host_config, const void *slot_config, sdmmc_card_t **out_card)
{
    esp_err_t err;
    sdmmc_card_t *card = NULL;

    // 1. 分配 card 结构体内存
    card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t));
    if (card == NULL)
    {
        ZYP_DEBUG_MMC("Failed to allocate memory for sdmmc_card_t");
    }
    memset(card, 0, sizeof(*card));

    // 2. 初始化主机控制器                  SDMMC 主机host初始化          ///will call back function sdmmc_host_init
    err = (*host_config->init)();
    if (err != ESP_OK)
    {
        ZYP_DEBUG_MMC(TAG, "Host init failed");
        goto fail;
    }

    // 3. 初始化插槽配置   gpio物理pin
    err = zyp_init_sdmmc_host(host_config->slot, slot_config, &card->host.slot);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "Slot init failed");
        goto deinit_host;
    }

#if 1
    // 4. 探测并初始化 eMMC 卡      init crad  send cmd
    err = zyp_sdmmc_card_init(host_config, card);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "sdmmc_card_init failed");
        goto deinit_slot;
    }
#endif
    if (out_card)
    {
        *out_card = card;
    }
    return ESP_OK;
deinit_slot:
    // 如果有插槽 deinit 函数，则调用
    if (host_config->flags & SDMMC_HOST_FLAG_DEINIT_ARG)
    {
        host_config->deinit_p(host_config->slot);
    }
    else
    {
        host_config->deinit();
    }
deinit_host:
    free(card);

fail:
    return err;
}

void zyp_sdmmc_card_print_info(FILE *stream, const sdmmc_card_t *card)
{
    bool print_scr = false;
    bool print_csd = false;
    const char *type;
    fprintf(stream, "Name: %s\n", card->cid.name);

    if (card->is_sdio)
    {
        type = "SDIO";
        print_scr = true;
        print_csd = true;
    }
    else if (card->is_mmc)
    {
        type = "MMC";
        print_csd = true;
    }
    else
    {
        type = (card->ocr & SD_OCR_SDHC_CAP) ? "SDHC/SDXC" : "SDSC";
        print_csd = true;
    }
    fprintf(stream, "Type: %s\n", type);

    if (card->real_freq_khz == 0)
    {
        fprintf(stream, "Speed: N/A\n");
    }
    else
    {
        const char *freq_unit = card->real_freq_khz < 1000 ? "kHz" : "MHz";
        const float freq = card->real_freq_khz < 1000 ? card->real_freq_khz : card->real_freq_khz / 1000.0;
        const char *max_freq_unit = card->max_freq_khz < 1000 ? "kHz" : "MHz";
        const float max_freq = card->max_freq_khz < 1000 ? card->max_freq_khz : card->max_freq_khz / 1000.0;
        fprintf(stream, "Speed: %.2f %s (limit: %.2f %s)%s\n", freq, freq_unit, max_freq, max_freq_unit, card->is_ddr ? ", DDR" : "");
    }

    fprintf(stream, "Size: %lluMB\n", ((uint64_t)card->csd.capacity) * card->csd.sector_size / (1024 * 1024));

    if (print_csd)
    {
        fprintf(stream, "CSD: ver=%d, sector_size=%d, capacity=%d read_bl_len=%d\n",
                (card->is_mmc ? card->csd.csd_ver : card->csd.csd_ver + 1),
                card->csd.sector_size, card->csd.capacity, card->csd.read_block_len);
        if (card->is_mmc)
        {
            fprintf(stream, "EXT CSD: bus_width=%d\n", (1 << card->log_bus_width));
        }
        else if (!card->is_sdio)
        { // make sure card is SD
            fprintf(stream, "SSR: bus_width=%d\n", (card->ssr.cur_bus_width ? 4 : 1));
        }
    }
    if (print_scr)
    {
        fprintf(stream, "SCR: sd_spec=%d, bus_width=%d\n", card->scr.sd_spec, card->scr.bus_width);
    }
}

esp_err_t zyp_cmd61(sdmmc_card_t *card)
{
    ZYP_DEBUG_MMC("send cmd61\n");
    sdmmc_command_t cmd = {
        .opcode = 61,
        .arg = 0x20464C4C,
        .flags = SCF_RSP_R0};
    return sdmmc_send_cmd(card, &cmd);
}

esp_err_t zyp_cmd0_go_idle_state(sdmmc_card_t *card)
{
    ZYP_DEBUG_MMC("send cmd0\n");
    sdmmc_command_t cmd = {
        .opcode = MMC_GO_IDLE_STATE,
        .flags = SCF_CMD_BC | SCF_RSP_R0,
    };
    return sdmmc_send_cmd(card, &cmd);
}

esp_err_t zyp_init_mmc(const sdmmc_host_t *config, sdmmc_card_t *card)
{
    ZYP_DEBUG_MMC("is_mem:%d\n", card->is_mem);
    ZYP_DEBUG_MMC("is_mmc:%d\n", card->is_mmc); /// 0 because mmc has no init？

    memset(card, 0, sizeof(*card));
    memcpy(&card->host, config, sizeof(*config));
    const bool is_spi = host_is_spi(card);
    ZYP_DEBUG_MMC("is_spi:%ld\n", (uint32_t)is_spi);

    const bool always = true;
    const bool io_supported = true;

    /* Check if host flags are compatible with slot configuration. */
    ZYP_SDMMC_INIT_FUN_STEP(!is_spi, sdmmc_fix_host_flags);
    ZYP_SDMMC_INIT_FUN_STEP(always, sdmmc_send_cmd_go_idle_state);

    const bool is_mem = card->is_mem;

    ZYP_SDMMC_INIT_FUN_STEP(always, sdmmc_init_ocr); /// CMD1

    const bool is_mmc = is_mem && card->is_mmc;

    /* Read the contents of CID register*/
    ZYP_SDMMC_INIT_FUN_STEP(always, sdmmc_init_cid); /// CMD2
    /* Assign RCA */
    ZYP_SDMMC_INIT_FUN_STEP(always, sdmmc_init_rca); /// CMD3
    /* Read and decode the contents of CSD register */
    //   ZYP_SDMMC_INIT_FUN_STEP(always, sdmmc_init_csd);               /// MMC CMD9 SEND_CSD

    /* Decode the contents of mmc CID register */
    ZYP_SDMMC_INIT_FUN_STEP(always, sdmmc_init_mmc_decode_cid);

    /* Switch the card from stand-by mode to data transfer mode (not needed if
     * SPI interface is used). This is needed to issue SET_BLOCKLEN and
     * SEND_SCR commands.
     */
    ZYP_SDMMC_INIT_FUN_STEP(always, sdmmc_init_select_card); /// MMC CMD7

    ZYP_DEBUG_MMC("is_mem:%d\n", card->is_mem);
    ZYP_DEBUG_MMC("is_mmc:%d\n", card->is_mmc);

    ZYP_SDMMC_INIT_FUN_STEP(always, sdmmc_init_mmc_read_ext_csd);

#if 0
    
    /* Try to switch card!!!!1 to HS mode if the card supports it.        ///切换为最大频率 200MHZ
     * Set card->max_freq_khz value accordingly.
     */
    ZYP_SDMMC_INIT_FUN_STEP(always, sdmmc_init_card_hs_mode);

    /* Set bus width. One call for every kind of card, then one for the host */
    if (!is_spi) {
        ZYP_SDMMC_INIT_FUN_STEP(is_sdmem, sdmmc_init_sd_bus_width);                ///根据当前crad的信息  send CMD6
        ZYP_SDMMC_INIT_FUN_STEP(is_sdio, sdmmc_init_io_bus_width);                 /// CMD52 
        ZYP_SDMMC_INIT_FUN_STEP(is_mmc, sdmmc_init_mmc_bus_width);
        ZYP_SDMMC_INIT_FUN_STEP(always, sdmmc_init_host_bus_width);
    }
    /* SD card: read SD Status register */
    ZYP_SDMMC_INIT_FUN_STEP(is_sdmem, sdmmc_init_sd_ssr);

    /* Switch to the host!!!! to use card->max_freq_khz frequency. */
    ZYP_SDMMC_INIT_FUN_STEP(always, sdmmc_init_host_frequency);

    /* Sanity check after switching the bus mode and frequency */
    ZYP_SDMMC_INIT_FUN_STEP(is_sdmem, sdmmc_check_scr);
    /* Sanity check after eMMC switch to HS mode */
    ZYP_SDMMC_INIT_FUN_STEP(is_mmc, sdmmc_init_mmc_check_ext_csd);
    /* TODO: add similar checks for SDIO */
#endif

    return ESP_OK;
}

esp_err_t zyp_mmc_send_cmd_send_op_cond(sdmmc_card_t *card)
{
    esp_err_t err = ESP_OK;

    int nretries = SDMMC_SEND_OP_COND_MAX_RETRIES;
    int err_cnt = SDMMC_SEND_OP_COND_MAX_ERRORS;

#if 0
 ///if clock is not always on, set it to always on
 if (card->host.set_cclk_always_on != NULL) {
    err = card->host.set_cclk_always_on(card->host.slot, true);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Failed to enable clock always-on");
        return err;
    }
}
#endif

    for (; nretries != 0; --nretries)
    {
        sdmmc_command_t cmd = {
            .arg = 0x40FF8080,
            .flags = SCF_CMD_BCR | SCF_RSP_R3,
            .opcode = MMC_SEND_OP_COND};

        err = sdmmc_send_cmd(card, &cmd);
        if (err != ESP_OK)
        { /// send err
            if (--err_cnt == 0)
            { /// retry max cnt
                ESP_LOGD(TAG, "%s: sdmmc_send_app_cmd err=0x%x", __func__, err);
                goto done;
            }
            else
            {
                ESP_LOGV(TAG, "%s: ignoring err=0x%x", __func__, err);
                continue; /// continue for  next retry
            }
        }

        if (!host_is_spi(card))
        { /// if not spi mode (mmc or sd but now is mmc ) if cmd resp
            if ((MMC_R3(cmd.response) & MMC_OCR_MEM_READY))
            { /// cmd.response meas  cmd.response[0]  32bit  cheack  bit 31 is 1 or not, 1 means ocr ready
                break;
            }
        }
        else
        {
            if ((SD_SPI_R1(cmd.response) & SD_SPI_R1_IDLE_STATE) == 0)
            {
                break;
            }
        }
        vTaskDelay(10 / portTICK_PERIOD_MS);
    }
done: /// close clock
    if (card->host.set_cclk_always_on != NULL)
    {
        esp_err_t err_cclk_dis = card->host.set_cclk_always_on(card->host.slot, false);
        if (err_cclk_dis != ESP_OK)
        {
            ESP_LOGE(TAG, "%s: set_cclk_always_on (2) err=0x%x", __func__, err);
            /* If we failed to disable clock, don't overwrite 'err' to return the original error */
        }
        ESP_LOGV(TAG, "%s: clock always-on mode disabled", __func__);
    }
    return err;
}

esp_err_t zyp_init_mmc_random(sdmmc_card_t *card)
{
    esp_err_t err;
    // ZYP_SDMMC_CHECK_CMD(zyp_cmd61(card), err, TAG, "cmd61 err");        ///uru Meditation Error: Core  0 panic'ed (IntegerDivideByZero). Exception was unhandled. reset esp32
    ZYP_SDMMC_CHECK_CMD(sdmmc_send_cmd_go_idle_state(card), err, TAG, "cmd0 err");
    vTaskDelay(pdMS_TO_TICKS(3000)); // watting FW printf done
    // card->ocr=0x40ff8080;
    card->is_mmc = 1;
    // ZYP_SDMMC_CHECK_CMD(sdmmc_send_cmd_send_op_cond(card, card->ocr, NULL), err, TAG, "cmd1 err");
    ZYP_SDMMC_CHECK_CMD(zyp_mmc_send_cmd_send_op_cond(card), err, TAG, "cmd1 err");
    // ZYP_SDMMC_CHECK_CMD(zyp_mmc_send_cmd_send_op_cond(card), err, TAG, "cmd1 err");
    // ZYP_SDMMC_CHECK_CMD(zyp_mmc_send_cmd_send_op_cond(card), err, TAG, "cmd1 err");
    ZYP_SDMMC_CHECK_CMD(sdmmc_send_cmd_all_send_cid(card, &card->raw_cid), err, TAG, "cmd2 err");

    ZYP_SDMMC_CHECK_CMD(sdmmc_send_cmd_set_relative_addr(card, &card->rca), err, TAG, "cmd3 err");

    ZYP_SDMMC_CHECK_CMD(sdmmc_send_cmd_send_csd(card, &card->csd), err, TAG, "cmd9 err");
    ZYP_SDMMC_CHECK_CMD(sdmmc_send_cmd_select_card(card, card->rca), err, TAG, "cmd7 err");
    ZYP_SDMMC_CHECK_CMD(sdmmc_init_mmc_read_ext_csd(card), err, TAG, "cmd8 err");

    ZYP_DEBUG_MMC("EMMC init success\n");
    if (card->is_mem && !card->is_sdio && card->is_mmc)
    {
        ESP_LOGI(TAG, "This is an eMMC card.");
    }

    return ESP_OK;
}

esp_err_t zyp_mmc_set_blocklen(sdmmc_card_t *card)
{
    sdmmc_command_t cmd = {
        .data = NULL, /// add new
        .opcode = MMC_SET_BLOCKLEN,
        .arg = card->csd.sector_size,
        .flags = SCF_CMD_AC | SCF_RSP_R1};
    return sdmmc_send_cmd(card, &cmd);
}

esp_err_t zyp_mmc_set_blocklcnt(sdmmc_command_t *cmd, sdmmc_card_t *card)
{
    // sdmmc_command_t cmd = {
    //     .opcode = MMC_SET_BLOCKLEN,
    //     .arg = block_count,
    //     .flags = SCF_CMD_AC | SCF_RSP_R1};
    return sdmmc_send_cmd(card, cmd);
}

esp_err_t zyp_mmc_send_status(sdmmc_card_t *card, uint32_t *out_status)
{
    sdmmc_command_t cmd = {
        .opcode = MMC_SEND_STATUS,
        .arg = MMC_ARG_RCA(card->rca),
        .flags = SCF_CMD_AC | SCF_RSP_R1};
    esp_err_t err = sdmmc_send_cmd(card, &cmd);
    if (err != ESP_OK)
    {
        return err;
    }
    if (out_status)
    {
        if (host_is_spi(card))
        {
            *out_status = SD_SPI_R2(cmd.response);
        }
        else
        {
            *out_status = MMC_R1(cmd.response); /// fectch  response[0]  soso first 0-32bit   beband 16bit hava 00 00 09 00
        }
    }
    return ESP_OK;
}

esp_err_t zyp_send_cmd60_cmd61_random(sdmmc_card_t *card, uint32_t value, uint8_t cmd_index)
{
    esp_err_t err;
    sdmmc_command_t cmd = {
        .opcode = cmd_index,
        .arg = value,
        .flags = SCF_CMD_AC | SCF_RSP_R0};
    if (cmd_index == MMC_APP_CMD60)
    {
        cmd.flags = SCF_RSP_R1;
    }
    err = sdmmc_send_cmd(card, &cmd);
    if (err != ESP_OK)
    {
        return err;
    }
    return ESP_OK;
}

esp_err_t zyp_mmc_random_write_read(sdmmc_card_t *card)
{
    esp_err_t err;
    uint32_t status;
    size_t addr = 1000;
    uint32_t block_count = 4;
#if IS_ENABLE_SEND_CMD_CSD
    size_t sector_size = card->csd.sector_size;
#else
    size_t sector_size = EXT_CSD_MMC_SIZE;
#endif
    size_t start_block = addr / sector_size;
    /// write read scope can not  exceed the card capacity
    if (start_block + block_count > card->csd.capacity)
    {
        ESP_LOGE(TAG, "Block range exceeds card capacity");
        return ESP_ERR_INVALID_SIZE;
    }
    /// alloc DMA-capable buffer
    uint8_t *write_buffer = heap_caps_malloc(sector_size * block_count, MALLOC_CAP_DMA);
    memset(write_buffer, 0X5A, sector_size * block_count);
    // for (size_t i = 0; i < card->csd.sector_size * block_count; i++)
    // {
    //     write_buffer[i] = i & 0xFF;
    // }

    if (!write_buffer)
    {
        ESP_LOGE(TAG, "Failed to allocate write_buffer");
        return ESP_ERR_NO_MEM;
    }
    uint8_t *read_buffer = heap_caps_malloc(sector_size * block_count, MALLOC_CAP_DMA);
    memset(read_buffer, 0, sector_size * block_count);
    if (!read_buffer)
    {
        ESP_LOGE(TAG, "Failed to allocate read buffer");
        return ESP_ERR_NO_MEM;
    }
    // ZYP_SDMMC_CHECK_CMD(zyp_mmc_set_blocklen(card), err, TAG, "cmd16 err");

    // ZYP_SDMMC_CHECK_CMD(zyp_mmc_set_blocklcnt(card,4), err, TAG, "cmd23 err");
    ZYP_SDMMC_CHECK_CMD(zyp_mmc_send_status(card, &status), err, TAG, "cmd13 err");

    ZYP_SDMMC_CHECK_CMD(sdmmc_write_sectors(card, write_buffer, start_block, block_count), err, TAG, "cmd25 err");

    // ZYP_SDMMC_CHECK_CMD(zyp_mmc_set_blocklcnt(card,4), err, TAG, "cmd23 err");
    // ZYP_SDMMC_CHECK_CMD(zyp_mmc_set_blocklen(card), err, TAG, "cmd16 err");
    ZYP_SDMMC_CHECK_CMD(sdmmc_read_sectors(card, read_buffer, start_block, block_count), err, TAG, "cmd18 err");

    for (size_t i = 0; i < card->csd.sector_size * block_count; i++)
    {
        ZYP_DEBUG_MMC("%02x ", (uint8_t)read_buffer[i]);
    }
    ZYP_DEBUG_MMC("\n");

    if (!write_buffer)
    {
        free(write_buffer);
    }
    if (!read_buffer)
    {
        free(read_buffer);
    }
    return ESP_OK;
}

esp_err_t zyp_switch_cmd(sdmmc_card_t *card, uint32_t value)
{
    sdmmc_command_t cmd = {
        .opcode = MMC_SWITCH,
        .arg = value,
        // .flags = SCF_RSP_R1 | SCF_CMD_AC,
        .flags = SCF_RSP_R1B | SCF_CMD_AC | SCF_WAIT_BUSY,
    };

    return sdmmc_send_cmd(card, &cmd);
}

esp_err_t zyp_sdmmc_switch_cmd_(sdmmc_card_t *card, uint8_t set, uint8_t index, uint8_t value)
{
    sdmmc_command_t cmd = {
        .opcode = MMC_SWITCH,
        .arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | (index << 16) | (value << 8) | set,
        .flags = SCF_RSP_R1B | SCF_CMD_AC | SCF_WAIT_BUSY,
    };
    esp_err_t err = sdmmc_send_cmd(card, &cmd);
    if (err == ESP_OK)
    {
        if (MMC_R1(cmd.response) & MMC_R1_SWITCH_ERROR)
        {
            err = ESP_ERR_INVALID_RESPONSE;
        }
    }

    return err;
}

esp_err_t zyp_sdmmc_configure_bus_fre_mode(sdmmc_card_t *card, uint32_t freq_khz, int bus_width, bool use_ddr)
{
    int slot = card->host.slot; /// use slot:1
    ZYP_DEBUG_MMC("card->host.slot: %d\n", card->host.slot);
    esp_err_t err;
    if (use_ddr)
    {
        card->is_ddr = 1;
        /// ddr mode must switch high speed？
        ZYP_SDMMC_CHECK_CMD(zyp_switch_cmd(card, HIGH_SPEED_VALUE), err, TAG, " high speed switch cmd err"); /// high speed     先切换hsp 在8bit  8bit swttch err
        ZYP_SDMMC_CHECK_CMD(sdmmc_host_set_card_clk(slot, freq_khz), err, TAG, " switch host clk err");
        if (bus_width == 4)
        {
            ZYP_SDMMC_CHECK_CMD(zyp_switch_cmd(card, DDR_4BIT_VALUE), err, TAG, " ddr 4bit switch cmd err"); /// sdr 8bit
        }
    }
    else
    {
        if (bus_width == 8)
        {
            ZYP_SDMMC_CHECK_CMD(zyp_switch_cmd(card, SDR_8BIT_VALUE), err, TAG, " sdr 8bit switch cmd err"); /// sdr 8bit
        }
        else if (bus_width == 4)
        {
            ZYP_SDMMC_CHECK_CMD(zyp_switch_cmd(card, SDR_4BIT_VALUE), err, TAG, " sdr 4bit switch cmd err"); /// sdr 8bit
        }
        else if (bus_width == 1)
        {
            ZYP_SDMMC_CHECK_CMD(zyp_switch_cmd(card, SDR_1BIT_VALUE), err, TAG, " sdr 1bit switch cmd err"); /// sdr 8bit
        }
    }
    // ZYP_SDMMC_CHECK_CMD(zyp_switch_cmd(card, 0x03B70600), err, TAG, " ddr 8bit switch cmd err"); /// ddr 8bit   noT suport   Wwrite crc err

    /// sdemmc switch bus_withc ddr mode
    // ZYP_SDMMC_CHECK_CMD(zyp_switch_cmd(card,0x03B70100),err,TAG," switch cmd err");         ///sdr 4bit    400k  06 8bit DDR err 02  8bit sdr err

    /// host config
    ZYP_DEBUG_MMC("slot:%d, freq_khz:%ld, bus_width:%d, use_ddr:%d\n", slot, freq_khz, bus_width, use_ddr);
    ZYP_SDMMC_CHECK_CMD(sdmmc_host_set_bus_width(slot, bus_width), err, TAG, " switch host bus err");
    ZYP_SDMMC_CHECK_CMD(sdmmc_host_set_bus_ddr_mode(slot, use_ddr), err, TAG, " switch host ddr err");

    return ESP_OK;
}

// 16-byte endian and little-endian conversion function
void reverse_cid_bytes(const uint32_t *response, uint8_t *cid)
{
    /* 转换逻辑：
     * 1. 反转response数组顺序（response[3]在前）
     * 2. 每个32位字按大端序拆解字节
     */
    for (int word_idx = 0; word_idx < 4; word_idx++)
    {
        // 取反序的32位字（从最后一个元素开始）
        uint32_t word = response[3 - word_idx];

        // 分解为4个字节（MSB first）
        cid[word_idx * 4 + 0] = (word >> 24) & 0xFF; // 最高有效字节
        cid[word_idx * 4 + 1] = (word >> 16) & 0xFF; // 取第三个字节
        cid[word_idx * 4 + 2] = (word >> 8) & 0xFF;
        cid[word_idx * 4 + 3] = word & 0xFF; // 最低有效字节
    }
}

esp_err_t zyp_sdmmc_init_cid(sdmmc_card_t *card)
{
    sdmmc_response_t raw_cid_t_;
    // assert()
    sdmmc_command_t cmd = {
        .opcode = MMC_ALL_SEND_CID,
        .flags = SCF_RSP_R2 | SCF_CMD_BCR};
    esp_err_t err = sdmmc_send_cmd(card, &cmd);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_MMC("send cmd err");
        return err;
    }
    memcpy(raw_cid_t_, &cmd.response, sizeof(sdmmc_response_t));

#if ID_ENABLE_PRINT_CID
    /// directly printf cmd.response  16byte
    ZYP_DEBUG_MMC("origanl CID response (16 bytes):\n");
    for (size_t i = 0; i < 4; i++)
    {
        ZYP_DEBUG_MMC("  %0lx", cmd.response[i]); // 打印每个 32 位字
    }
    ZYP_DEBUG_MMC("\n");

    /// ZYP_DEBUG_MMC("change CID response (16 bytes):\n")
    uint8_t cid[16];
    reverse_cid_bytes(cmd.response, cid);
    /// Print the converted CID
    ZYP_DEBUG_MMC("Corrected CID:");
    for (int i = 0; i < 16; i++)
    {
        ZYP_DEBUG_MMC("%02X", cid[i]); // 连续打印
    }
    ZYP_DEBUG_MMC("\n");
#endif

    return ESP_OK;
}

esp_err_t zyp_sdmmc_send_cmd_set_relative_addr(sdmmc_card_t *card, uint16_t *out_rca)
{
    return sdmmc_send_cmd_set_relative_addr(card, out_rca);
}

esp_err_t zyp_mmc_send_cmd_select_card(sdmmc_card_t *card, uint32_t rca)
{

    /* Don't expect to see a response when de-selecting a card */
    // uint32_t response = (rca == 0) ? 0 : SCF_RSP_R1;
    sdmmc_command_t cmd = {
        .opcode = MMC_SELECT_CARD,
        .arg = MMC_ARG_RCA(rca),
        .flags = SCF_RSP_R1B

    };
    return sdmmc_send_cmd(card, &cmd);
}

esp_err_t zyp_sdmmc_send_cmd_send_csd(sdmmc_card_t *crad, sdmmc_csd_t *out_csd)
{
    return sdmmc_send_cmd_send_csd(crad, out_csd);
}

// esp_err_t zyp_write_sector_sdmmc(size_t sector_size,
//                                      size_t addr,
//                                      uint32_t lba,
//                                      uint32_t offset,
//                                      size_t size,
//                                      const void *src)
// {
//     return sdmmc_write_sectors(s_storage_handle->card, src, lba, size / sector_size);
// }
/// esp_err_t sdmmc_write_sectors(sdmmc_card_t* card, const void* src,
// size_t start_block, size_t block_count)

esp_err_t zyp_write_psram_to_emmc(sdmmc_card_t *card, uint8_t *psram_addr, size_t data_size, size_t start_block) ///  psram_addr:esp32 memory addr   start_block cmd25parm    data_size:write——size block unit
{
    ZYP_DEBUG_MMC("zyp_write_psram_to_emmc\n");
    size_t sector_size = card->csd.sector_size;
    ZYP_DEBUG_MMC("card->csd.sector_size:%d\n", sector_size);
    if (sector_size == 0)
        return ESP_ERR_INVALID_SIZE;

    // 向上取整
    size_t block_count = (data_size + sector_size - 1) / sector_size; /// data_size/sector_size向下取整    llf  block_count  55KB

    /// SEND CMD23
#if 0
    cmd->opcode = MMC_SET_BLOCK_COUNT;
    cmd->arg =block_count; 
    cmd->data = NULL;                
    ZYP_DEBUG_MMC("cmd23_parm::%d\n", (unsigned int)block_count);
    if (sdmmc_send_cmd(card, cmd))
    {
        ZYP_DEBUG_MMC("zyp_setBlockCountCmd ERR\n");
    }
    ZYP_DEBUG_MMC("CMD23 OVER ERR\n");
    
     vTaskDelay(pdMS_TO_TICKS(500));
#endif

    ZYP_DEBUG_MMC("block_count:%d\n", block_count);

    ZYP_DEBUG_MMC("file addr:%p\n", psram_addr);
    ZYP_DEBUG_MMC("card->csd.capacity:%d\n", card->csd.capacity);

    // if (start_block + block_count > card->csd.capacity)
    // {
    //     ESP_LOGE(TAG, "Write range exceeds eMMC capacity");
    //     return ESP_ERR_INVALID_SIZE;
    // }
#if ENABLE_4BYT_ALIGNM_EDMA_WRITE
    uint8_t *dma_buf = heap_caps_malloc(sector_size * block_count, MALLOC_CAP_DMA);
    if (!dma_buf)
    {
        ESP_LOGE(TAG, "Failed to allocate DMA buffer for write");
        return ESP_ERR_NO_MEM;
    }
    memcpy(dma_buf, psram_addr, sector_size * block_count);
    for (size_t i = 0; i < 128; i++)
    {
        ZYP_DEBUG_MMC("%02X ", dma_buf[i]);
        if (i == 127)
        {
            ZYP_DEBUG_MMC("\n");
        }
    }

#endif

#if ENABLE_NOT_ALIGNM_EDMA_WRITE
    esp_err_t err = sdmmc_write_sectors(card, psram_addr, start_block, block_count);
#endif

#if ENABLE_4BYT_ALIGNM_EDMA_WRITE
    esp_err_t err = sdmmc_write_sectors(card, dma_buf, start_block, block_count);
#endif
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "Failed to write to eMMC: %s", esp_err_to_name(err));
        return err;
    }

#if ENABLE_NOT_ALIGNM_EDMA_WRITE
    uint8_t *verify_buf = heap_caps_malloc(sector_size * block_count, MALLOC_CAP_DMA);
    if (!verify_buf)
        return ESP_ERR_NO_MEM;

    err = sdmmc_read_sectors(card, verify_buf, start_block, block_count);
    if (err != ESP_OK || memcmp(psram_addr, verify_buf, data_size) != 0)
    {
        ESP_LOGE(TAG, "Data verification failed");
        free(verify_buf);
        return ESP_ERR_INVALID_CRC;
    }
#endif
    // free(verify_buf);
    // if(!dma_buf)
    if (dma_buf != NULL)
    {
        free(dma_buf); /// must be free   either or  the third time  will be error ！！！！！！
        // dma_buf=NULL;
    }
    return ESP_OK;
}

#if VERIFY_EMMC_CASE

esp_err_t zyp_mmc_clear_emmc(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responseBuffer, MMC_FORCE_CLEAN_T *force_clean, uint8_t clean_totalbyte)
{

    ZYP_DEBUG_VERIFY_CASE("clean_totalbyte:%d\n ", clean_totalbyte);
    esp_err_t err;
    memset(requestbuffer, 0, sizeof(struct RequestBuffer));
    sdmmc_command_t cmd_set_blocklen = {
        .data = NULL, /// add new
        .opcode = MMC_SET_BLOCKLEN,
        .arg = clean_totalbyte,
        .flags = SCF_CMD_AC | SCF_RSP_R1};
    err = sdmmc_send_cmd(card, &cmd_set_blocklen);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("MMC_SET_BLOCKLEN err\n");
        return err;
    }

    sdmmc_command_t cmd_clean = {
        .blklen = clean_totalbyte,
        .arg = 0x00000000,
        .data = (char *)force_clean,
        .datalen = clean_totalbyte,
        .flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_WAIT_BUSY,
        .opcode = MMC_LOCK_UNLOCK,
        .timeout_ms = SDMMC_WRITE_CMD_TIMEOUT_MS,
        .no_need_auto_stop = 1,
    };
    requestbuffer->cmdId = cmd_clean.opcode;
    requestbuffer->cmdParm = cmd_clean.arg;
    err = zyp_mmc_write_sectors(&cmd_clean, card, requestbuffer, force_clean, 0, 100);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("MMC_EXECUTE_WRITE_TASK err\n");
        return ESP_FAIL;
    }

#if 0
    ///cmd16 set block len 512
    sdmmc_command_t cmd_set_blocklen_512 = {
        .data = NULL, /// add new
        .opcode = MMC_SET_BLOCKLEN,
        .arg = 512,
        .flags = SCF_CMD_AC | SCF_RSP_R1};
    err = sdmmc_send_cmd(card, &cmd_set_blocklen_512);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("MMC_SET_BLOCKLEN err\n");
        return err;
    }
#endif
    return ESP_OK;
}

esp_err_t zyp_mmc_lock_unlock(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responseBuffer, MMC_LOCK_T *lock, uint8_t write_totalbyte)
{
    ZYP_DEBUG_VERIFY_CASE("write_totalbyte:%d\n ", write_totalbyte);
    esp_err_t err;
    memset(requestbuffer, 0, sizeof(struct RequestBuffer));
    sdmmc_command_t cmd_set_blocklen = {
        .data = NULL, /// add new
        .opcode = MMC_SET_BLOCKLEN,
        .arg = write_totalbyte,
        .flags = SCF_CMD_AC | SCF_RSP_R1};

    err = sdmmc_send_cmd(card, &cmd_set_blocklen);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("MMC_SET_BLOCKLEN err\n");
        // return err;
    }

    sdmmc_command_t cmd_lock = {
        .blklen = write_totalbyte,
        .arg = 0x00000000,
        .data = (char *)lock,
        .datalen = write_totalbyte,
        .flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_WAIT_BUSY,
        .opcode = MMC_LOCK_UNLOCK,
        .timeout_ms = SDMMC_WRITE_CMD_TIMEOUT_MS,
        // .no_need_auto_stop =1,                           ///origal jus is not auoto stop
    };
    requestbuffer->cmdId = cmd_lock.opcode;
    requestbuffer->cmdParm = cmd_lock.arg;
    err = zyp_mmc_write_sectors(&cmd_lock, card, requestbuffer, lock, 0, 1);

    ZYP_DEBUG_VERIFY_CASE("%d\n", __LINE__);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("MMC_EXECUTE_WRITE_TASK err\n");
        return ESP_FAIL;
    }

#if 0
    ///cmd16 set block len 512
    sdmmc_command_t cmd_set_blocklen_512 = {
        .data = NULL, /// add new
        .opcode = MMC_SET_BLOCKLEN,
        .arg = 512,
        .flags = SCF_CMD_AC | SCF_RSP_R1};
    err = sdmmc_send_cmd(card, &cmd_set_blocklen_512);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("MMC_SET_BLOCKLEN err\n");
        return err;
    }
#endif

    return ESP_OK;
}

void zyp_read_cid(sdmmc_card_t *card)
{
    esp_err_t err;
    ZYP_DEBUG("Initializing host done\n");
    card->is_mmc = 1;
    // 2. CMD0: GO_IDLE_STATE
    ZYP_DEBUG("CMD0 zyp_cmd0_go_idle_state \n");
    err = zyp_cmd0_go_idle_state(card);
    if (err != ESP_OK)
    {
        ZYP_DEBUG("CMD0 failed:");
        // return err;
    }

    ZYP_DEBUG("CMD1 zyp_mmc_send_cmd_send_op_cond \n");

    // 3. CMD1: SEND_OP_COND
    err = zyp_mmc_send_cmd_send_op_cond(card);
    if (err != ESP_OK)
    {
        ZYP_DEBUG("CMD1 failed:");
        // return err;
    }

    ZYP_DEBUG("CMD2 zyp_sdmmc_init_cid \n");

    //  todo  CMD2: ALL_SEND_CID    why  print stack????
    //     sdmmc_response_t raw_cid_;
    //      sdmmc_command_t cmd={
    //         .opcode = MMC_ALL_SEND_CID,
    //         .flags=SCF_RSP_R2| SCF_CMD_BCR
    //     };
    //     err= sdmmc_send_cmd(card,&cmd);
    //    if (err !=ESP_OK)
    //    {
    //       ZYP_DEBUG("send cmd err");
    //     //   return err;
    //    }
    //    ZYP_DEBUG("zyp_sdmmc_init_cid OK\n");
    //    for (size_t i = 0; i < 4; i++)
    //    {
    //         ZYP_DEBUG("0x%02lx", cmd.response[i]);
    //    }
    zyp_sdmmc_init_cid(card);
}

#if IS_FFU_MDDE

esp_err_t zyp_ffu_download_general(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer, uint8_t *ext_csd_buffer)
{
    esp_err_t err;
#if 1
    // uint8_t *ext_csd_buffer = (uint8_t *)heap_caps_malloc(sizeof(uint8_t) * EXT_CSD_MMC_SIZE, MALLOC_CAP_8BIT);
    // if (!ext_csd_buffer)
    // {
    //     ZYP_DEBUG_MMC("malloc ext_csd_buffer err\n");
    // }
    memset(ext_csd_buffer, 0, sizeof(uint8_t) * EXT_CSD_MMC_SIZE);

    /// similotor host cmd8 fream
    requestbuffer->cmdParm = 0;
    requestbuffer->cmdId = MMC_SEND_EXT_CSD;
    // err = zyp_sdmmc_init_mmc_read_ext_csd(card, cmd, requestbuffer, responsebuffer, ext_csd_buffer);  ///sendcmd8 and change host config flag

    sdmmc_command_t cmd8 = {0};
    // err = zyp_sdmmc_mmc_send_ext_csd_data(card, ext_csd_buffer, EXT_CSD_MMC_SIZE, cmd, requestbuffer);  ///just send cmd8   bug！！！ cmd8的cmd 在zyp_sdmmc_mmc_send_ext_csd_data后面填充,之后cmd25又用到，导致cmd25发timeout
    err = zyp_sdmmc_mmc_send_ext_csd_data(card, ext_csd_buffer, EXT_CSD_MMC_SIZE, &cmd8, requestbuffer);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_MMC("zyp_sdmmc_init_mmc_read_ext_csd err\n");
        heap_caps_free(ext_csd_buffer);
        return err;
    }
    for (size_t i = 0; i < EXT_CSD_MMC_SIZE; i++)
    {
        ZYP_DEBUG_MMC("[%d]=0x%02x ", i, (size_t)ext_csd_buffer[i]);
    }
    ZYP_DEBUG_MMC("\n");

    if (!(ext_csd_buffer[EXT_CSD_SUPPORTED_MODES] & 0x01)) /// if 0
    {
        ZYP_DEBUG_MMC("Device does not support FFU functionality.\n");
        heap_caps_free(ext_csd_buffer);
        return err;
    }

    if (ext_csd_buffer[EXT_CSD_FW_CONFIG] & 0x01)
    {
        ZYP_DEBUG_MMC("Firmware updates are disabled. Cannot proceed with FFU.\n");
        free(ext_csd_buffer);
        return ESP_FAIL;
    }
#endif
    // 将MODE_CONFIG[30]字段切换到FFU模式
    // err=zyp_sdmmc_switch_cmd_(card,0,0X1E,1);
    err = zyp_switch_cmd(card, 0x031E0100);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_MMC("Failed to switch to FFU mode.\n");
        // free(ext_csd_buffer);
        return ESP_FAIL;
    }

    /// cmd13
    uint32_t cmd13_status;
    err = zyp_mmc_send_status(card, &cmd13_status);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_MMC("zyp_mmc_send_status err\n");
        return err;
    }

    return ESP_OK;
}

esp_err_t zyp_ffu_download_powercycle(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer)
{
    if (ffu_binfile_reciveover == true)
    {
        esp_err_t err;
#if 1
        uint8_t *ext_csd_buffer = (uint8_t *)heap_caps_malloc(sizeof(uint8_t) * EXT_CSD_MMC_SIZE, MALLOC_CAP_8BIT);
        if (!ext_csd_buffer)
        {
            ZYP_DEBUG_MMC("malloc ext_csd_buffer err\n");
        }
        memset(ext_csd_buffer, 0, sizeof(uint8_t) * EXT_CSD_MMC_SIZE);

        /// similotor host cmd8 fream
        requestbuffer->cmdParm = 0;
        requestbuffer->cmdId = MMC_SEND_EXT_CSD;
        // err = zyp_sdmmc_init_mmc_read_ext_csd(card, cmd, requestbuffer, responsebuffer, ext_csd_buffer);  ///sendcmd8 and change host config flag

        sdmmc_command_t cmd8 = {0};
        // err = zyp_sdmmc_mmc_send_ext_csd_data(card, ext_csd_buffer, EXT_CSD_MMC_SIZE, cmd, requestbuffer);  ///just send cmd8   bug！！！ cmd8的cmd 在zyp_sdmmc_mmc_send_ext_csd_data后面填充,之后cmd25又用到，导致cmd25发timeout
        err = zyp_sdmmc_mmc_send_ext_csd_data(card, ext_csd_buffer, EXT_CSD_MMC_SIZE, &cmd8, requestbuffer);
        if (err != ESP_OK)
        {
            ZYP_DEBUG_MMC("zyp_sdmmc_init_mmc_read_ext_csd err\n");
            heap_caps_free(ext_csd_buffer);
            return err;
        }
        for (size_t i = 0; i < EXT_CSD_MMC_SIZE; i++)
        {
            ZYP_DEBUG_MMC("[%d]=0x%02x ", i, (size_t)ext_csd_buffer[i]);
        }
        ZYP_DEBUG_MMC("\n");

        if (!(ext_csd_buffer[EXT_CSD_SUPPORTED_MODES] & 0x01)) /// if 0
        {
            ZYP_DEBUG_MMC("Device does not support FFU functionality.\n");
            heap_caps_free(ext_csd_buffer);
            return err;
        }

        if (ext_csd_buffer[EXT_CSD_FW_CONFIG] & 0x01)
        {
            ZYP_DEBUG_MMC("Firmware updates are disabled. Cannot proceed with FFU.\n");
            free(ext_csd_buffer);
            return ESP_FAIL;
        }
#endif
        // 将MODE_CONFIG[30]字段切换到FFU模式
        // err=zyp_sdmmc_switch_cmd_(card,0,0X1E,1);
        err = zyp_switch_cmd(card, 0x031E0100);
        if (err != ESP_OK)
        {
            ZYP_DEBUG_MMC("Failed to switch to FFU mode.\n");
            free(ext_csd_buffer);
            return ESP_FAIL;
        }

        /// cmd13
        uint32_t cmd13_status;
        err = zyp_mmc_send_status(card, &cmd13_status);
        if (err != ESP_OK)
        {
            ZYP_DEBUG_MMC("zyp_mmc_send_status err\n");
            return err;
        }

#if 1
        // 计算固件包大小与EXT_CSD中的DATA_SECTOR_SIZE对齐
        size_t ffu_arg = ext_csd_buffer[EXT_CSD_FFU_ARG_0] | ext_csd_buffer[EXT_CSD_FFU_ARG_1] << 8 | ext_csd_buffer[EXT_CSD_FFU_ARG_2] << 16 | ext_csd_buffer[EXT_CSD_FFU_ARG_3] << 24;
        ZYP_DEBUG_MMC("FFU_ARG:0x%02x\n", ffu_arg);

        // size_t ffu_arg = 0xFFFAFFF0;
        size_t data_sector_size = 0;
        if (ext_csd_buffer[EXT_CSD_DATA_SECTOR_SIZE] == 0) // 默认512
        {
            data_sector_size = EXT_CSD_MMC_SIZE;
        }
        else if (ext_csd_buffer[EXT_CSD_DATA_SECTOR_SIZE] == 1)
        {
            data_sector_size = 4 * 2 * EXT_CSD_MMC_SIZE; /// 4K
        }
        size_t cmd25_parm_ffu = ffu_arg;
        ZYP_DEBUG_MMC("data_sector_size:0x%02x,cmd25_parm_ffu:0x%02x\n", (size_t)data_sector_size, (size_t)cmd25_parm_ffu);
#endif

        size_t ffu_file_byte_size = EXT_CSD_MMC_SIZE;

        memset(requestbuffer, 0, sizeof(struct RequestBuffer));
        requestbuffer->requestDirection = 0;
        requestbuffer->cmdId = MMC_WRITE_BLOCK_MULTIPLE;
        requestbuffer->cmdParm = cmd25_parm_ffu;
        // requestbuffer->cmdParm = 0xFFFAFFF0;
        requestbuffer->requestDirection = 0;
        requestbuffer->rwFlag = 0x02;
        requestbuffer->respType = 0x01;
        requestbuffer->endBit = 0x1111; /// ffu flage

        uint8_t *ffu_file_start_addr = psram_base + FFU_FILE * FILE_SLOT_SIZE;
        ZYP_DEBUG_MMC("psram_base addr: %p\n ", psram_base);
        ZYP_DEBUG_MMC("virigin_file_size_t.main_file_size: %d\n", virigin_file_size_t.ffu_file_size);
        for (size_t i = 0; i < 10; i++)
        {
            ZYP_DEBUG_MMC("%02x ", ffu_file_start_addr[i]);
        }
        size_t ffu_file_blocks_ = (virigin_file_size_t.ffu_file_size + EXT_CSD_MMC_SIZE - 1) / EXT_CSD_MMC_SIZE;
        ZYP_DEBUG_MMC("\nffu_file_blocks_: %d\n", ffu_file_blocks_);

        err = zyp_mmc_write_sectors(cmd, card, requestbuffer, ffu_file_start_addr, /// parm 5 nouse
                                    0, ffu_file_blocks_);
        if (err != ESP_OK)
        {
            ZYP_DEBUG_MMC("FFU write err\n ");
            return err;
        }
        else
        {
            ZYP_DEBUG_MMC("FFU write success\n ");
            virigin_file_size_t.ffu_file_size = 0;
            ffu_file_index_startbit = 0;
            current_file_index = LLF_FILE;
        }

#if 1
        /// send cmd Trigger FW firmware update, juedg  FFU_FEATURES [492] value
        uint8_t MODE_OPERATION_CODES = ext_csd_buffer[EXT_CSD_FFU_FEATURES];
        if (MODE_OPERATION_CODES == 0) /// MODE_OPERATION_CODES not supported
        {
            err = zyp_switch_cmd(card, 0x031E0000);
            if (err != ESP_OK)
            {
                ZYP_DEBUG_MMC("Failed to switch to nomal mode.\n");
                free(ext_csd_buffer);
                return ESP_FAIL;
            }
            else
            {
                ZYP_DEBUG_MMC("Switch to MODE_OPERATION_CODES[30] normal mode successfully.\n");
            }
        }

        else if (MODE_OPERATION_CODES == 1)
        {
            /// host cmd6 switch MODE_OPERATION_CODES [29]   FFU_INSTALL (0x01)   EMMC will be auto updata FW
            err = zyp_switch_cmd(card, 0x031D0100); /// annonce fw up  emmc firmeware
            if (err != ESP_OK)
            {
                ZYP_DEBUG_MMC("Failed to switch to FFU mode.\n");
                free(ext_csd_buffer);
                return ESP_FAIL;
            }
        }
    }
#endif
    return ESP_OK;
}
#endif

esp_err_t zyp_ffu_download_cmd0(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer, uint8_t *ext_csd_buffer)
{
    esp_err_t err;
    if (ffu_binfile_reciveover == true)
    {
        if (zyp_ffu_download_general(cmd, card, requestbuffer, responsebuffer, ext_csd_buffer) != ESP_OK)
        {
            return ESP_FAIL;
        }
#if 1
        // 计算固件包大小与EXT_CSD中的DATA_SECTOR_SIZE对齐
        size_t ffu_arg = ext_csd_buffer[EXT_CSD_FFU_ARG_0] | ext_csd_buffer[EXT_CSD_FFU_ARG_1] << 8 | ext_csd_buffer[EXT_CSD_FFU_ARG_2] << 16 | ext_csd_buffer[EXT_CSD_FFU_ARG_3] << 24;
        ZYP_DEBUG_MMC("FFU_ARG:0x%02x\n", ffu_arg);

        // size_t ffu_arg = 0xFFFAFFF0;
        size_t data_sector_size = 0;
        if (ext_csd_buffer[EXT_CSD_DATA_SECTOR_SIZE] == 0) // 默认512
        {
            data_sector_size = EXT_CSD_MMC_SIZE;
        }
        else if (ext_csd_buffer[EXT_CSD_DATA_SECTOR_SIZE] == 1)
        {
            data_sector_size = 4 * 2 * EXT_CSD_MMC_SIZE; /// 4K
        }
        size_t cmd25_parm_ffu = ffu_arg;
        ZYP_DEBUG_MMC("data_sector_size:0x%02x,cmd25_parm_ffu:0x%02x\n", (size_t)data_sector_size, (size_t)cmd25_parm_ffu);
#endif

        size_t ffu_file_byte_size = EXT_CSD_MMC_SIZE;

        memset(requestbuffer, 0, sizeof(struct RequestBuffer));
        requestbuffer->requestDirection = 0;
        requestbuffer->cmdId = MMC_WRITE_BLOCK_MULTIPLE;
        requestbuffer->cmdParm = cmd25_parm_ffu;
        // requestbuffer->cmdParm = 0xFFFAFFF0;
        requestbuffer->requestDirection = 0;
        requestbuffer->rwFlag = 0x02;
        requestbuffer->respType = 0x01;
        requestbuffer->endBit = 0x1111; /// ffu flage

        uint8_t *ffu_file_start_addr = psram_base + FFU_FILE * FILE_SLOT_SIZE;
        ZYP_DEBUG_MMC("psram_base addr: %p\n ", psram_base);
        ZYP_DEBUG_MMC("virigin_file_size_t.main_file_size: %d\n", virigin_file_size_t.ffu_file_size);
        for (size_t i = 0; i < 10; i++)
        {
            ZYP_DEBUG_MMC("%02x ", ffu_file_start_addr[i]);
        }
        size_t ffu_file_blocks_ = (virigin_file_size_t.ffu_file_size + EXT_CSD_MMC_SIZE - 1) / EXT_CSD_MMC_SIZE;
        ZYP_DEBUG_MMC("\nffu_file_blocks_: %d\n", ffu_file_blocks_);

        err = zyp_mmc_write_sectors(cmd, card, requestbuffer, ffu_file_start_addr, /// parm 5 nouse
                                    0, ffu_file_blocks_);
        if (err != ESP_OK)
        {
            ZYP_DEBUG_MMC("FFU write err\n ");
            return err;
        }
        else
        {
            ZYP_DEBUG_MMC("FFU write success\n ");
            virigin_file_size_t.ffu_file_size = 0;
            ffu_file_index_startbit = 0;
            current_file_index = LLF_FILE;
        }

#if 1
        /// send cmd Trigger FW firmware update, juedg  FFU_FEATURES [492] value
        uint8_t MODE_OPERATION_CODES = ext_csd_buffer[EXT_CSD_FFU_FEATURES];
        if (MODE_OPERATION_CODES == 0) /// MODE_OPERATION_CODES not supported
        {
            err = zyp_switch_cmd(card, 0x031E0000);
            if (err != ESP_OK)
            {
                ZYP_DEBUG_MMC("Failed to switch to nomal mode.\n");
                // return ESP_FAIL;         /// no return
            }
            else
            {
                ZYP_DEBUG_MMC("Switch to MODE_OPERATION_CODES[30] normal mode successfully.\n");
            }
            
#if 0
            for (size_t i = 0; i < 5; i++)       ///fix fw 来不急hanlde cmd0           fw resovled  in  dnln , ffu mode set MODE_OPERATION_CODESp[30] is nomal mode  not set edc_clear_device_busy();
            {
                uint32_t cmd13_status;
                err = zyp_mmc_send_status(card, &cmd13_status);
                if (err != ESP_OK)
                {
                    ZYP_DEBUG_MMC("zyp_mmc_send_status err\n");
                    return err;
                }
            }
#endif

#if 1
            zyp_cmd0_go_idle_state(card);
            zyp_init_mmc_random(card); /// VCMDID 00  MMC init
            zyp_sdmmc_configure_bus_fre_mode(card, SDMMC_FREQ_PROBING, 1, 0);
#if 1
            slot_config.width = BUS_WITH_1BIT;
            ZYP_SDMMC_CHECK_CMD(sdmmc_host_init_slot(card->host.slot, &slot_config), err, TAG, "host_init_slot err");
            card->host.set_bus_width(card->host.slot, BUS_WITH_1BIT);
#endif
            ZYP_SDMMC_CHECK_CMD(sdmmc_host_set_card_clk(card->host.slot, SDMMC_FREQ_PROBING), err, TAG, " switch host clk err");
            ZYP_SDMMC_CHECK_CMD(sdmmc_host_set_bus_width(card->host.slot, BUS_WITH_1BIT), err, TAG, " switch host bus err");
            ZYP_SDMMC_CHECK_CMD(sdmmc_host_set_bus_ddr_mode(card->host.slot, 0), err, TAG, " switch host ddr err");
#endif
        }

        else if (MODE_OPERATION_CODES == 1)
        {
            /// host cmd6 switch MODE_OPERATION_CODES [29]   FFU_INSTALL (0x01)   EMMC will be auto updata FW
            err = zyp_switch_cmd(card, 0x031D0100); /// annonce fw up  emmc firmeware
            if (err != ESP_OK)
            {
                ZYP_DEBUG_MMC("Failed to switch to FFU mode.\n");
                return ESP_FAIL;
            }
        }
    }
#endif
    return ESP_OK;
}

esp_err_t zyp_ffu_download_hardreset(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer, uint8_t *ext_csd_buffer)
{
    esp_err_t err;
    if (ffu_binfile_reciveover == true)
    {
        if (zyp_ffu_download_general(cmd, card, requestbuffer, responsebuffer, ext_csd_buffer) != ESP_OK)
        {
            return ESP_FAIL;
        }

        /// enable hard reset mode
        if (ext_csd_buffer[EXT_CSD_RST_N_FUNCTION] ==0)
        {
            err = zyp_switch_cmd(card, 0x03A20100);
            if (err != ESP_OK)
            {
                ZYP_DEBUG_MMC("Failed to switch to enable reset_n.\n");
                return ESP_FAIL;
            }
        }
#if 1
        // 计算固件包大小与EXT_CSD中的DATA_SECTOR_SIZE对齐
        size_t ffu_arg = ext_csd_buffer[EXT_CSD_FFU_ARG_0] | ext_csd_buffer[EXT_CSD_FFU_ARG_1] << 8 | ext_csd_buffer[EXT_CSD_FFU_ARG_2] << 16 | ext_csd_buffer[EXT_CSD_FFU_ARG_3] << 24;
        ZYP_DEBUG_MMC("FFU_ARG:0x%02x\n", ffu_arg);

        // size_t ffu_arg = 0xFFFAFFF0;
        size_t data_sector_size = 0;
        if (ext_csd_buffer[EXT_CSD_DATA_SECTOR_SIZE] == 0) // 默认512
        {
            data_sector_size = EXT_CSD_MMC_SIZE;
        }
        else if (ext_csd_buffer[EXT_CSD_DATA_SECTOR_SIZE] == 1)
        {
            data_sector_size = 4 * 2 * EXT_CSD_MMC_SIZE; /// 4K
        }
        size_t cmd25_parm_ffu = ffu_arg;
        ZYP_DEBUG_MMC("data_sector_size:0x%02x,cmd25_parm_ffu:0x%02x\n", (size_t)data_sector_size, (size_t)cmd25_parm_ffu);
#endif

        size_t ffu_file_byte_size = EXT_CSD_MMC_SIZE;

        memset(requestbuffer, 0, sizeof(struct RequestBuffer));
        requestbuffer->requestDirection = 0;
        requestbuffer->cmdId = MMC_WRITE_BLOCK_MULTIPLE;
        requestbuffer->cmdParm = cmd25_parm_ffu;
        // requestbuffer->cmdParm = 0xFFFAFFF0;
        requestbuffer->requestDirection = 0;
        requestbuffer->rwFlag = 0x02;
        requestbuffer->respType = 0x01;
        requestbuffer->endBit = 0x1111; /// ffu flage

        uint8_t *ffu_file_start_addr = psram_base + FFU_FILE * FILE_SLOT_SIZE;
        ZYP_DEBUG_MMC("psram_base addr: %p\n ", psram_base);
        ZYP_DEBUG_MMC("virigin_file_size_t.main_file_size: %d\n", virigin_file_size_t.ffu_file_size);
        for (size_t i = 0; i < 10; i++)
        {
            ZYP_DEBUG_MMC("%02x ", ffu_file_start_addr[i]);
        }
        size_t ffu_file_blocks_ = (virigin_file_size_t.ffu_file_size + EXT_CSD_MMC_SIZE - 1) / EXT_CSD_MMC_SIZE;
        ZYP_DEBUG_MMC("\nffu_file_blocks_: %d\n", ffu_file_blocks_);

        err = zyp_mmc_write_sectors(cmd, card, requestbuffer, ffu_file_start_addr, /// parm 5 nouse
                                    0, ffu_file_blocks_);
        if (err != ESP_OK)
        {
            ZYP_DEBUG_MMC("FFU write err\n ");
            return err;
        }
        else
        {
            ZYP_DEBUG_MMC("FFU write success\n ");
            virigin_file_size_t.ffu_file_size = 0;
            ffu_file_index_startbit = 0;
            current_file_index = LLF_FILE;
        }

#if 1
        /// send cmd Trigger FW firmware update, juedg  FFU_FEATURES [492] value
        uint8_t MODE_OPERATION_CODES = ext_csd_buffer[EXT_CSD_FFU_FEATURES];
        if (MODE_OPERATION_CODES == 0) /// MODE_OPERATION_CODES not supported
        {
            err = zyp_switch_cmd(card, 0x031E0000);
            if (err != ESP_OK)
            {
                ZYP_DEBUG_MMC("Failed to switch to nomal mode.\n");
                return ESP_FAIL;
            }
            else
            {
                ZYP_DEBUG_MMC("Switch to MODE_OPERATION_CODES[30] normal mode successfully.\n");
            }

            uint32_t cmd13_status;
            err = zyp_mmc_send_status(card, &cmd13_status);
            if (err != ESP_OK)
            {
                ZYP_DEBUG_MMC("zyp_mmc_send_status err\n");
                return err;
            }
            vTaskDelay(pdMS_TO_TICKS(1000));

            ZYP_DEBUG_MMC("Hard_Reset_N\n");
            emmc_rst_pin_init();
            vTaskDelay(pdMS_TO_TICKS(1000));
            emmc_hardware_reset();

            vTaskDelay(pdMS_TO_TICKS(1000));
#if 1
            slot_config.width = BUS_WITH_1BIT;
            ZYP_SDMMC_CHECK_CMD(sdmmc_host_init_slot(card->host.slot, &slot_config), err, TAG, "host_init_slot err");
            card->host.set_bus_width(card->host.slot, BUS_WITH_1BIT);
#endif
            ZYP_SDMMC_CHECK_CMD(sdmmc_host_set_card_clk(card->host.slot, SDMMC_FREQ_PROBING), err, TAG, " switch host clk err");
            ZYP_SDMMC_CHECK_CMD(sdmmc_host_set_bus_width(card->host.slot, BUS_WITH_1BIT), err, TAG, " switch host bus err");
            ZYP_SDMMC_CHECK_CMD(sdmmc_host_set_bus_ddr_mode(card->host.slot, 0), err, TAG, " switch host ddr err");
        }

        else if (MODE_OPERATION_CODES == 1)
        {
            /// host cmd6 switch MODE_OPERATION_CODES [29]   FFU_INSTALL (0x01)   EMMC will be auto updata FW
            err = zyp_switch_cmd(card, 0x031D0100); /// annonce fw up  emmc firmeware
            if (err != ESP_OK)
            {
                ZYP_DEBUG_MMC("Failed to switch to FFU mode.\n");
                return ESP_FAIL;
            }
        }
    }
#endif
    return ESP_OK;
}

#define SMI 1
esp_err_t zyp_ffu_download_random_write(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer, uint8_t *ext_csd_buffer)
{
    esp_err_t err;
    if (zyp_ffu_download_general(cmd, card, requestbuffer, responsebuffer, ext_csd_buffer) != ESP_OK)
    {
        return ESP_FAIL;
    }
#if 1
    size_t ffu_arg = ext_csd_buffer[EXT_CSD_FFU_ARG_0] | ext_csd_buffer[EXT_CSD_FFU_ARG_1] << 8 | ext_csd_buffer[EXT_CSD_FFU_ARG_2] << 16 | ext_csd_buffer[EXT_CSD_FFU_ARG_3] << 24;
    ZYP_DEBUG_MMC("FFU_ARG:0x%02x\n", ffu_arg);
    size_t data_sector_size = 0;
    if (ext_csd_buffer[EXT_CSD_DATA_SECTOR_SIZE] == 0) // 默认512
    {
        data_sector_size = EXT_CSD_MMC_SIZE;
    }
    else if (ext_csd_buffer[EXT_CSD_DATA_SECTOR_SIZE] == 1)
    {
        data_sector_size = 4 * 2 * EXT_CSD_MMC_SIZE; /// 4K
    }
    size_t cmd25_parm_ffu = ffu_arg;
    ZYP_DEBUG_MMC("data_sector_size:0x%02x,cmd25_parm_ffu:0x%02x\n", (size_t)data_sector_size, (size_t)cmd25_parm_ffu);
#endif

#if SMI
    // size_t ffu_file_byte_size = EXT_CSD_MMC_SIZE;
    size_t ffu_file_byte_size = 64 * 1024;
#else
            size_t ffu_file_byte_size = EXT_CSD_MMC_SIZE;
#endif
    size_t ffu_file_blocks = ffu_file_byte_size / EXT_CSD_MMC_SIZE;
    uint8_t *write_buffer_ffu = (uint8_t *)heap_caps_malloc(ffu_file_byte_size, MALLOC_CAP_DMA);
    memset(write_buffer_ffu, 0x5A, ffu_file_byte_size);

    memset(requestbuffer, 0, sizeof(struct RequestBuffer)); /// consrtuct fake cmdfraem
    requestbuffer->requestDirection = 0;
    requestbuffer->cmdId = MMC_WRITE_BLOCK_MULTIPLE;
    requestbuffer->cmdParm = cmd25_parm_ffu;
    requestbuffer->requestDirection = 0;
    requestbuffer->rwFlag = 0x02;
    requestbuffer->respType = 0x01;
    requestbuffer->endBit = 0x1111; /// ffu flage

    // err = zyp_write_psram_to_emmc(card, write_buffer_ffu, ffu_file_byte_size, cmd25_parm_ffu);
    size_t ffu_file_blocks_ = (virigin_file_size_t.ffu_file_size + EXT_CSD_MMC_SIZE - 1) / EXT_CSD_MMC_SIZE;
    err = zyp_mmc_write_sectors(cmd, card, requestbuffer, write_buffer_ffu, /// parm 5 nouse
                                0, ffu_file_blocks_);

    if (err != ESP_OK)
    {
        ZYP_DEBUG_MMC("write_buffer_ffu err\n");
        heap_caps_free(write_buffer_ffu);
        return err;
    }
    if (write_buffer_ffu != NULL)
    {
        heap_caps_free(write_buffer_ffu);
    }
    requestbuffer->endBit = 0x7A; /// 用于resp to window

#if 1
    /// send cmd Trigger FW firmware update, juedg  FFU_FEATURES [492] value
    uint8_t MODE_OPERATION_CODES = ext_csd_buffer[EXT_CSD_FFU_FEATURES];
    if (MODE_OPERATION_CODES == 0) /// MODE_OPERATION_CODES not supported
    {
        err = zyp_switch_cmd(card, 0x031E0000);
        if (err != ESP_OK)
        {
            ZYP_DEBUG_MMC("Failed to switch to nomal mode.\n");
            return ESP_FAIL;
        }
        else
        {
            ZYP_DEBUG_MMC("Switch to MODE_OPERATION_CODES[30] normal mode successfully.\n");
        }
        /// poweron way
    }

    else if (MODE_OPERATION_CODES == 1)
    {
        /// host cmd6 switch MODE_OPERATION_CODES [29]   FFU_INSTALL (0x01)   EMMC will be auto updata FW
        err = zyp_switch_cmd(card, 0x031D0100);
        if (err != ESP_OK)
        {
            ZYP_DEBUG_MMC("Failed to switch to FFU mode.\n");
            return ESP_FAIL;
        }
    }

#if 0    
    memset(requestbuffer, 0, sizeof(struct RequestBuffer));
    requestbuffer->cmdParm = 0;
    requestbuffer->cmdId = MMC_SEND_EXT_CSD;
    /// Cheack FFU_STATUS [26]   Using this field the device reports the status of the FFU process
    err = zyp_sdmmc_mmc_send_ext_csd_data(card, ext_csd_buffer, EXT_CSD_MMC_SIZE, &cmd8, requestbuffer); /// just send cmd8
    if (err != ESP_OK)
    {
        ZYP_DEBUG_MMC("zyp_sdmmc_init_mmc_read_ext_csd err\n");
        heap_caps_free(ext_csd_buffer);
        return err;
    }

    switch (ext_csd_buffer[EXT_CSD_FFU_STATUS])
    {
    case 0x00:
        ZYP_DEBUG_MMC("FFU instal success\n");
        break;
    case 0x01:
        ZYP_DEBUG_MMC("FFU  General error\n");
        break;
    case 0x11:
        ZYP_DEBUG_MMC("FFU  Firmware install error\n");
        break;
    case 0x12:
        ZYP_DEBUG_MMC("FFU  Error in downloading firmware\n");
        break;
    default:
        ZYP_DEBUG_MMC("FFU  Unknown error\n");
        break;
    }
    if (ext_csd_buffer[EXT_CSD_FFU_STATUS] != 0)
    {
        return -1;
    }

    if (ext_csd_buffer != NULL)
    {
        heap_caps_free(ext_csd_buffer);
    }
#endif

#endif
    return ESP_OK;
}

esp_err_t zyp_ffu_download_cmd25_parm_err(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer, uint8_t *ext_csd_buffer)
{
    esp_err_t err;
    if (ffu_binfile_reciveover == true)
    {
        if (zyp_ffu_download_general(cmd, card, requestbuffer, responsebuffer, ext_csd_buffer) != ESP_OK)
        {
            return ESP_FAIL;
        }
#if 1
        // 计算固件包大小与EXT_CSD中的DATA_SECTOR_SIZE对齐
        size_t ffu_arg = ext_csd_buffer[EXT_CSD_FFU_ARG_0] | ext_csd_buffer[EXT_CSD_FFU_ARG_1] << 8 | ext_csd_buffer[EXT_CSD_FFU_ARG_2] << 16 | ext_csd_buffer[EXT_CSD_FFU_ARG_3] << 24;
        ZYP_DEBUG_MMC("FFU_ARG:0x%02x\n", ffu_arg);

        // size_t ffu_arg = 0xFFFAFFF0;
        size_t data_sector_size = 0;
        if (ext_csd_buffer[EXT_CSD_DATA_SECTOR_SIZE] == 0) // 默认512
        {
            data_sector_size = EXT_CSD_MMC_SIZE;
        }
        else if (ext_csd_buffer[EXT_CSD_DATA_SECTOR_SIZE] == 1)
        {
            data_sector_size = 4 * 2 * EXT_CSD_MMC_SIZE; /// 4K
        }

#endif

        size_t ffu_file_byte_size = EXT_CSD_MMC_SIZE;
        size_t cmd25_parm_ffu = 0xffffffff;
        memset(requestbuffer, 0, sizeof(struct RequestBuffer));
        requestbuffer->requestDirection = 0;
        requestbuffer->cmdId = MMC_WRITE_BLOCK_MULTIPLE;
        requestbuffer->cmdParm = cmd25_parm_ffu;
        // requestbuffer->cmdParm = 0xFFFAFFF0;
        requestbuffer->requestDirection = 0;
        requestbuffer->rwFlag = 0x02;
        requestbuffer->respType = 0x01;
        requestbuffer->endBit = 0x1111; /// ffu flage

        uint8_t *ffu_file_start_addr = psram_base + FFU_FILE * FILE_SLOT_SIZE;
        ZYP_DEBUG_MMC("psram_base addr: %p\n ", psram_base);
        ZYP_DEBUG_MMC("virigin_file_size_t.main_file_size: %d\n", virigin_file_size_t.ffu_file_size);
        for (size_t i = 0; i < 10; i++)
        {
            ZYP_DEBUG_MMC("%02x ", ffu_file_start_addr[i]);
        }
        size_t ffu_file_blocks_ = (virigin_file_size_t.ffu_file_size + EXT_CSD_MMC_SIZE - 1) / EXT_CSD_MMC_SIZE;
        ZYP_DEBUG_MMC("\nffu_file_blocks_: %d\n", ffu_file_blocks_);

        err = zyp_mmc_write_sectors(cmd, card, requestbuffer, ffu_file_start_addr, /// parm 5 nouse
                                    0, ffu_file_blocks_);
        if (err != ESP_OK)
        {
            ZYP_DEBUG_MMC("FFU write err\n ");
            return err;
        }
        else
        {
            ZYP_DEBUG_MMC("FFU write success\n ");
            virigin_file_size_t.ffu_file_size = 0;
            ffu_file_index_startbit = 0;
            current_file_index = LLF_FILE;
        }

#if 1
        /// send cmd Trigger FW firmware update, juedg  FFU_FEATURES [492] value
        uint8_t MODE_OPERATION_CODES = ext_csd_buffer[EXT_CSD_FFU_FEATURES];
        if (MODE_OPERATION_CODES == 0) /// MODE_OPERATION_CODES not supported
        {
            err = zyp_switch_cmd(card, 0x031E0000);
            if (err != ESP_OK)
            {
                ZYP_DEBUG_MMC("Failed to switch to nomal mode.\n");
                return ESP_FAIL;
            }
            else
            {
                ZYP_DEBUG_MMC("Switch to MODE_OPERATION_CODES[30] normal mode successfully.\n");
            }

            uint32_t cmd13_status;
            err = zyp_mmc_send_status(card, &cmd13_status);
            if (err != ESP_OK)
            {
                ZYP_DEBUG_MMC("zyp_mmc_send_status err\n");
                return err;
            }
        }

        else if (MODE_OPERATION_CODES == 1)
        {
            /// host cmd6 switch MODE_OPERATION_CODES [29]   FFU_INSTALL (0x01)   EMMC will be auto updata FW
            err = zyp_switch_cmd(card, 0x031D0100); /// annonce fw up  emmc firmeware
            if (err != ESP_OK)
            {
                ZYP_DEBUG_MMC("Failed to switch to FFU mode.\n");
                return ESP_FAIL;
            }
        }
    }
#endif
    return ESP_OK;
}

#endif /// #if IS_FFU_MDDE

esp_err_t zyp_mmc_create_cmdq_task_read(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer, uint taskId, uint number_block, uint lba)
{
    esp_err_t err;
    int i;
    size_t qsr;
    int retry_count = 0;
    const int max_retries = 500;

    sdmmc_command_t cmd_queued_task_param_read = {
        .opcode = MMC_QUEUED_TASK_PARAMS,
        .arg = ((taskId & 0x1f) << 16) | (1 << 30) | (number_block & 0xFFFF), /// bit 0-15 block bit 30 write read
        .data = NULL,
        .flags = SCF_CMD_AC | SCF_RSP_R1};
    // ZYP_DEBUG_VERIFY_CASE("cmdqwite parm:%08x\n", (size_t)cmd_queued_task_param_write.arg);
    if (sdmmc_send_cmd(card, &cmd_queued_task_param_read) != ESP_OK) /// 0 ok
    {
        ZYP_DEBUG_VERIFY_CASE("cmd44 err\n");
        return ESP_FAIL;
    }

    sdmmc_command_t cmd_queued_task_addr_read = {
        .opcode = MMC_QUEUED_TASK_ADDRESS,
        .arg = lba, /// bit 0-15 block bit 30 is_packed
        .data = NULL,
        .flags = SCF_CMD_AC | SCF_RSP_R1};
    if (sdmmc_send_cmd(card, &cmd_queued_task_addr_read) != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("err cmd45\n");
        return ESP_FAIL;
    }
    card->rca = 1;
    sdmmc_command_t cmd_status = {
        .opcode = MMC_SEND_STATUS,
        .arg = MMC_ARG_RCA(card->rca) | 0x8000,
        .flags = SCF_CMD_AC | SCF_RSP_R1};
    do
    {
        err = sdmmc_send_cmd(card, &cmd_status);
        if (err != ESP_OK)
        {
            ZYP_DEBUG_VERIFY_CASE("err cmd31: %s\n", esp_err_to_name(err));
            return ESP_FAIL;
        }
        qsr = MMC_R1(cmd_status.response);
        ZYP_DEBUG_VERIFY_CASE("cmd_status->response[0]: %08x\n", qsr);
        for (i = 0; i < 4; i++)
        {
            printf("cmd_status->response[%d]: %x  ", i, (size_t)cmd_status.response[i]);
        }
        ZYP_DEBUG_VERIFY_CASE("\n");
        ZYP_DEBUG_VERIFY_CASE("(qsr & (1 << taskId): %08x\n", (qsr & (1 << taskId)));
        if ((qsr & (1 << taskId)) != 0) /// wait for fw
        {
            ZYP_DEBUG_VERIFY_CASE("Task %u is ready for execution\n", taskId);
            break;
        }
        retry_count++;
        if (retry_count >= max_retries)
        {
            ZYP_DEBUG_VERIFY_CASE("Timeout: Task %u is not ready after %d retries\n", taskId, max_retries);
            return ESP_FAIL;
        }
        vTaskDelay(1);
    } while (1);

    uint8_t *queen_buffer_read = (uint8_t *)heap_caps_malloc(number_block * EXT_CSD_MMC_SIZE, MALLOC_CAP_DMA);
    sdmmc_command_t cmd_read_task = {
        /// cmd47 write  the lowest esp32  not auto send cmd12 stop
        .opcode = MMC_EXECUTE_READ_TASK,
        .arg = (taskId & 0x1F) << 16,
        .flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_WAIT_BUSY, /// no need auto stop
        .timeout_ms = SDMMC_WRITE_CMD_TIMEOUT_MS,
        .blklen = EXT_CSD_MMC_SIZE,
        .datalen = number_block * EXT_CSD_MMC_SIZE, /// read buffer size
        .data = queen_buffer_read,
    };
    requestbuffer->cmdId = cmd_read_task.opcode;
    requestbuffer->cmdParm = cmd_read_task.arg;
    err = zyp_sendReadCmd(&cmd_read_task, card, requestbuffer, (unsigned int *)queen_buffer_read, 0, number_block);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("CMD46 err\n");
        return ESP_FAIL;
    }
    if (queen_buffer_read != NULL)
    {
        free(queen_buffer_read);
        queen_buffer_read = NULL;
    }
    ZYP_DEBUG_VERIFY_CASE("mmc_create_task_write end\n");
    return ESP_OK;
}

#if 1
esp_err_t zyp_mmc_create_cmdq_task_write(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer, uint taskId, uint number_block, uint lba)
{
    esp_err_t err;
    int i;
    size_t qsr;
    int retry_count = 0;
    const int max_retries = 500;

    sdmmc_command_t cmd_queued_task_param_write = {
        .opcode = MMC_QUEUED_TASK_PARAMS,
        .arg = ((taskId & 0x1f) << 16) | (0 << 30) | (number_block & 0xFFFF), /// bit 0-15 block bit 30 write read
        .data = NULL,
        .flags = SCF_CMD_AC | SCF_RSP_R1};
    ZYP_DEBUG_VERIFY_CASE("cmdqwite parm:%08x\n", (size_t)cmd_queued_task_param_write.arg);
    if (sdmmc_send_cmd(card, &cmd_queued_task_param_write) != ESP_OK) /// 0 ok
    {
        ZYP_DEBUG_VERIFY_CASE("cmd44 err\n");
        return ESP_FAIL;
    }

    sdmmc_command_t cmd_queued_task_addr_write = {
        .opcode = MMC_QUEUED_TASK_ADDRESS,
        .arg = lba, /// bit 0-15 block bit 30 is_packed
        .data = NULL,
        .flags = SCF_CMD_AC | SCF_RSP_R1};
    if (sdmmc_send_cmd(card, &cmd_queued_task_addr_write) != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("err cmd45\n");
        return ESP_FAIL;
    }

    card->rca = 1;
    sdmmc_command_t cmd_status = {
        .opcode = MMC_SEND_STATUS,
        .arg = MMC_ARG_RCA(card->rca) | 0x8000,
        .flags = SCF_CMD_AC | SCF_RSP_R1};
    do
    {
        err = sdmmc_send_cmd(card, &cmd_status);
        if (err != ESP_OK)
        {
            ZYP_DEBUG_VERIFY_CASE("err cmd13: %s\n", esp_err_to_name(err));
            return ESP_FAIL;
        }
        // qsr = MMC_R1(cmd_status.response);
        ZYP_DEBUG_VERIFY_CASE("MMC_R1(cmd_status.response) %08x\n", (unsigned int)MMC_R1(cmd_status.response));
        qsr = cmd_status.response[0];
        ZYP_DEBUG_VERIFY_CASE("cmd_status->response[0]: %08x\n", qsr);
        for (i = 0; i < 4; i++)
        {
            printf("cmd_status->response[%d]: %08x  ", i, (size_t)cmd_status.response[i]);
        }
        ZYP_DEBUG_VERIFY_CASE("\n");
        ZYP_DEBUG_VERIFY_CASE("(qsr & (1 << taskId): %08x\n", (qsr & (1 << taskId)));
        if ((qsr & (1 << taskId)) != 0) /// wait for fw
        {
            ZYP_DEBUG_VERIFY_CASE("Task %u is ready for execution\n", taskId);
            break;
        }

        retry_count++;
        if (retry_count >= max_retries)
        {
            ZYP_DEBUG_VERIFY_CASE("Timeout: Task %u is not ready after %d retries\n", taskId, max_retries);
            return ESP_FAIL;
        }
        vTaskDelay(1);

    } while (1);

    uint8_t *queen_buf = (uint8_t *)heap_caps_malloc(EXT_CSD_MMC_SIZE * 20, MALLOC_CAP_DMA);
    if (lba == 0)
    {
        memset(queen_buf, 0x5B, EXT_CSD_MMC_SIZE * number_block);
    }
    else if (lba == 1)
    {
        memset(queen_buf, 0x5C, EXT_CSD_MMC_SIZE * number_block);
    }
    else
    {
        memset(queen_buf, 0x5D, EXT_CSD_MMC_SIZE * number_block);
    }

    sdmmc_command_t cmd_wirte_task = {
        /// cmd47 write  the lowest esp32  not auto send cmd12 stop
        .opcode = MMC_EXECUTE_WRITE_TASK,
        .arg = (taskId & 0x1F) << 16, /// taskid  propotion 5bit [20:16]
        .flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_WAIT_BUSY,
        .timeout_ms = SDMMC_WRITE_CMD_TIMEOUT_MS,
        .blklen = EXT_CSD_MMC_SIZE,
        .datalen = number_block * EXT_CSD_MMC_SIZE,
        .data = queen_buf,
    };

    requestbuffer->cmdId = cmd_wirte_task.opcode;
    requestbuffer->cmdParm = cmd_wirte_task.arg;
    err = zyp_mmc_write_sectors(&cmd_wirte_task, card, requestbuffer, queen_buf, 0, number_block);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("MMC_EXECUTE_WRITE_TASK err\n");
        return ESP_FAIL;
    }

    ZYP_DEBUG_VERIFY_CASE("mmc_create_task_write end\n");
    if (queen_buf != NULL)
    {
        free(queen_buf);
    }

    return ESP_OK;
}
#endif

esp_err_t zyp_mmc_packed_write(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer, size_t *address, size_t *block_counts, size_t num_entries, size_t *write_data)
{
    esp_err_t err;
    size_t t_block_size_byte = 0;
    size_t total_blocks = 0;
    memset(requestbuffer, 0, sizeof(struct RequestBuffer));
    ZYP_DEBUG_VERIFY_CASE("num_entries:%d\n", num_entries);
    for (size_t i = 0; i < num_entries; i++) /// num_entries   how many addr
    {
        total_blocks += block_counts[i];
    }
    total_blocks++;

    ZYP_DEBUG_VERIFY_CASE("total_blocks:%d\n ", total_blocks);
    t_block_size_byte = total_blocks * EXT_CSD_MMC_SIZE;
    // uint8_t *packed_cmd_buf = (uint8_t *)heap_caps_aligned_alloc(sizeof(uint8_t), t_block_size_byte, MALLOC_CAP_DMA); /// 1 byte alay
    uint8_t *packed_cmd_buf = (uint8_t *)heap_caps_malloc(t_block_size_byte, MALLOC_CAP_DMA);
    ZYP_DEBUG_VERIFY_CASE("%d\n ", __LINE__);
    memset(packed_cmd_buf, 0, t_block_size_byte);
    uint8_t *packe_header = packed_cmd_buf;
    packe_header[0] = MMC_PACKED_VERSION;
    packe_header[1] = MMC_PACKED_W_FLAGS;
    packe_header[2] = num_entries;

    for (size_t i = 0; i < num_entries; i++)
    {
        size_t entry_offset = MMC_PACKED_EVY_BLACNT_ADD_SHIF_BYTE + MMC_PACKED_EVY_BLACNT_ADD_SHIF_BYTE * i;
        memcpy((uint8_t *)packe_header + entry_offset, &block_counts[i], sizeof(size_t));
        memcpy((uint8_t *)packe_header + entry_offset + sizeof(size_t), &address[i], sizeof(size_t));
    }

    size_t da_offset = EXT_CSD_MMC_SIZE;
    for (size_t i = 0; i < num_entries; i++)
    {
        memcpy((uint8_t *)packe_header + da_offset, &write_data[i], block_counts[i] * EXT_CSD_MMC_SIZE);
        da_offset += block_counts[i] * EXT_CSD_MMC_SIZE;
    }

    ZYP_DEBUG_VERIFY_CASE("packet write header: ");
    /// construct over   debug
    for (size_t i = 0; i < 8 + 8 * num_entries; i++)
    {
        ZYP_DEBUG_VERIFY_CASE("%02x ", packe_header[i]);
    }
    ZYP_DEBUG_VERIFY_CASE("\n");

    sdmmc_command_t cmd_set_cnt = {
        .opcode = MMC_SET_BLOCK_COUNT,
        .arg = (total_blocks & 0XFFFF) | (1 << 30), /// bit 0-15 block bit 30 is_packed
        .flags = SCF_CMD_AC | SCF_RSP_R1};

    if (zyp_mmc_set_blocklcnt(&cmd_set_cnt, card))
    {
        ZYP_DEBUG_VERIFY_CASE("err setblock:\n");
    }

    // sdmmc_write_sectors(card, packe_header, address[0], total_blocks);
#if 1
    requestbuffer->cmdId = MMC_WRITE_BLOCK_MULTIPLE;
    requestbuffer->cmdParm = total_blocks;
    sdmmc_command_t cmd_write_block = {
        .opcode = MMC_WRITE_BLOCK_MULTIPLE,
        .flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_WAIT_BUSY,
        .blklen = EXT_CSD_MMC_SIZE,
        .datalen = total_blocks * EXT_CSD_MMC_SIZE,
        .data = (void *)packe_header,
        .timeout_ms = SDMMC_WRITE_CMD_TIMEOUT_MS,
        .no_need_auto_stop = 1,
    };
    err = zyp_mmc_write_sectors(&cmd_write_block, card, requestbuffer, (void *)packe_header, address[0], total_blocks);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("err write: %s\n", esp_err_to_name(err));
    }
#endif
    if (packed_cmd_buf != NULL)
    {
        free(packed_cmd_buf);
        // packed_cmd_buf = NULL;
    }
    memset(requestbuffer, 0, sizeof(struct RequestBuffer));
    return ESP_OK;
}

esp_err_t zyp_mmc_packed_read(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer, uint *addresses, uint *block_counts, uint num_entries)
{
    esp_err_t err;
    int blocks_size = 0;
    size_t total_blocks = 0;
    size_t i = 0;

    for (size_t i = 0; i < num_entries; i++)
    {
        total_blocks += block_counts[i];
    }
    ZYP_DEBUG_VERIFY_CASE(" total_blocks: %d\n", total_blocks);

    uint8_t *packed_cmd_buf_read = (uint8_t *)heap_caps_malloc(EXT_CSD_MMC_SIZE * 1, MALLOC_CAP_DMA);
    if (packed_cmd_buf_read == NULL)
    {
        return ESP_FAIL;
    }
    memset(packed_cmd_buf_read, 0, EXT_CSD_MMC_SIZE * 1);
    char *header = (char *)packed_cmd_buf_read;
    header[0] = 0x01; // Version
    // header[1] = 0x02;
    header[1] = 0x01;
    header[2] = num_entries;
    ZYP_DEBUG_VERIFY_CASE("num_entries: %d\n", num_entries);
    for (i = 0; i < num_entries; i++)
    {
        // num_entries:2
        uint32_t entry_offset = 8 + (i * 8);
        memcpy((char *)header + entry_offset, &block_counts[i], sizeof(uint32_t));
        memcpy((char *)header + entry_offset + sizeof(uint32_t), &addresses[i], sizeof(uint32_t));
    }
    ZYP_DEBUG_VERIFY_CASE("packet read header: ");
    /// construct over   debug
    for (size_t i = 0; i < 8 + 8 * num_entries; i++)
    {
        ZYP_DEBUG_VERIFY_CASE("%02x ", header[i]);
    }
    ZYP_DEBUG_VERIFY_CASE("\n");

    sdmmc_command_t cmd_set_cnt_cmd = {
        .opcode = MMC_SET_BLOCK_COUNT,
        .arg = (1 & 0XFFFF) | (1 << 30), /// bit 0-15 block bit 30 is_packed
        .flags = SCF_CMD_AC | SCF_RSP_R1};
    if (zyp_mmc_set_blocklcnt(&cmd_set_cnt_cmd, card))
    {
        ZYP_DEBUG_VERIFY_CASE("err setblock:\n");
    }

#if 1
    requestbuffer->cmdId = MMC_WRITE_BLOCK_MULTIPLE;
    requestbuffer->cmdParm = 1;
    sdmmc_command_t cmd_write_block = {
        .opcode = MMC_WRITE_BLOCK_MULTIPLE,
        .flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_WAIT_BUSY,
        .blklen = EXT_CSD_MMC_SIZE,
        .datalen = 1 * EXT_CSD_MMC_SIZE,
        .data = (void *)header,
        .timeout_ms = SDMMC_WRITE_CMD_TIMEOUT_MS,
        .no_need_auto_stop = 1,
    };
    err = zyp_mmc_write_sectors(&cmd_write_block, card, requestbuffer, (void *)header, 0, 1);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("err write: %s\n", esp_err_to_name(err));
    }
#endif
    if (packed_cmd_buf_read != NULL)
    {
        free(packed_cmd_buf_read);
        packed_cmd_buf_read = NULL;
    }

    ZYP_DEBUG_VERIFY_CASE("     packed_read_total_blocks: %d\n", total_blocks);
    sdmmc_command_t cmd_set_cnt_cmd_read = {
        .opcode = MMC_SET_BLOCK_COUNT,
        .arg = (total_blocks & 0XFFFF) | (1 << 30), /// bit 0-15 block bit 30 is_packed
        .flags = SCF_CMD_AC | SCF_RSP_R1};
    if (zyp_mmc_set_blocklcnt(&cmd_set_cnt_cmd_read, card))
    {
        ZYP_DEBUG_VERIFY_CASE("CMD23_packed err setblock:\n");
    }

    uint8_t *buffer_r = (uint8_t *)heap_caps_malloc(EXT_CSD_MMC_SIZE * total_blocks, MALLOC_CAP_DMA);
    requestbuffer->cmdId = MMC_READ_BLOCK_MULTIPLE;
    requestbuffer->cmdParm = addresses[0];
    sdmmc_command_t cmd_read_block_cmd = {
        .opcode = MMC_READ_BLOCK_MULTIPLE,
        .flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_WAIT_BUSY, /// .flags recacultor  in zyp_sdmmc_read_sectors_dma
        .blklen = EXT_CSD_MMC_SIZE,
        .datalen = total_blocks * EXT_CSD_MMC_SIZE,
        .data = (void *)buffer_r,
        .timeout_ms = SDMMC_WRITE_CMD_TIMEOUT_MS,
        .no_need_auto_stop = 1,
    };

    err = zyp_sendReadCmd(&cmd_read_block_cmd, card, requestbuffer, (unsigned int *)buffer_r, addresses[0], total_blocks); /// param  start_block, no use
    if (err != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("err read: %s\n", esp_err_to_name(err));
    }
    else
    {
        ZYP_DEBUG_VERIFY_CASE("packed read buffer_r: \n");
        for (size_t i = 0; i < total_blocks * EXT_CSD_MMC_SIZE; i++)
        {
            ZYP_DEBUG_VERIFY_CASE("%02x ", buffer_r[i]);
        }
    }

    if (buffer_r != NULL)
    {
        free(buffer_r);
    }
    memset(requestbuffer, 0, sizeof(struct RequestBuffer));
    return err;
}

esp_err_t zyp_mmc_old_erase_group(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer, size_t write_block_cnt)
{
    esp_err_t err;
    uint8_t *write_buffer = (uint8_t *)heap_caps_malloc(EXT_CSD_MMC_SIZE * write_block_cnt, MALLOC_CAP_DMA);
    memset(write_buffer, 0x5A, EXT_CSD_MMC_SIZE * write_block_cnt);

    sdmmc_command_t cmd_switch = {
        .opcode = MMC_SWITCH,
        .arg = 0x03AF0000,
        .flags = SCF_RSP_R1B | SCF_CMD_AC | SCF_WAIT_BUSY,
    };
    return sdmmc_send_cmd(card, &cmd_switch);

    sdmmc_command_t cmd_set_cnt_cmd = {
        .opcode = MMC_SET_BLOCK_COUNT,
        .arg = write_block_cnt, /// 1 erase group size 512K
        .flags = SCF_CMD_AC | SCF_RSP_R1};
    if (zyp_mmc_set_blocklcnt(&cmd_set_cnt_cmd, card))
    {
        ZYP_DEBUG_VERIFY_CASE("err setblock:\n");
    }

#if 1
    requestbuffer->cmdId = MMC_WRITE_BLOCK_MULTIPLE;
    requestbuffer->cmdParm = 1; /// FE as todo flags
    sdmmc_command_t cmd_write_block = {
        .opcode = MMC_WRITE_BLOCK_MULTIPLE,
        .flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_WAIT_BUSY,
        .blklen = EXT_CSD_MMC_SIZE,
        .datalen = write_block_cnt * EXT_CSD_MMC_SIZE,
        .data = (void *)write_buffer,
        .timeout_ms = SDMMC_WRITE_CMD_TIMEOUT_MS,
        .no_need_auto_stop = 1,
        .arg = 0, /// add 0 start R/W
    };
    err = zyp_mmc_write_sectors(&cmd_write_block, card, requestbuffer, (void *)write_buffer, 0, 1);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("err write: %s\n", esp_err_to_name(err));
    }
#endif
    if (write_buffer != NULL)
    {
        free(write_buffer);
        write_buffer = NULL;
    }
    ZYP_DEBUG_VERIFY_CASE("-------------write %d cnt end-------------\n", write_block_cnt);
    vTaskDelay(pdMS_TO_TICKS(50));
    sdmmc_command_t cmd_state = {
        .opcode = MMC_SEND_STATUS,
        .arg = MMC_ARG_RCA(card->rca),
        .flags = SCF_CMD_AC | SCF_RSP_R1};
    for (size_t i = 0; i < 5; i++)
    {
        err = sdmmc_send_cmd(card, &cmd_state);
        if (cmd_state.response[0] == MMC_TRANSFER_STATE)
        {
            break;
        }
    }
    if (err != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("-------------cmd13 state err-------------\n");
        return err;
    }
}

esp_err_t zyp_boot1_add_perm_wp(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer)
{
    esp_err_t err;
    // reset init
    zyp_init_mmc_random(card); /// VCMDID 00  MMC init
    zyp_sdmmc_configure_bus_fre_mode(card, SDMMC_FREQ_PROBING, 1, 0);

    /// cmd8 ext_csd 173 174 is 0
    uint8_t *ext_csd = heap_caps_malloc(EXT_CSD_MMC_SIZE, MALLOC_CAP_DMA);
    sdmmc_command_t cmd_ext_csd = {
        .opcode = MMC_SEND_EXT_CSD,
        .flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_CMD_READ,
        .datalen = EXT_CSD_MMC_SIZE,
        .blklen = EXT_CSD_MMC_SIZE,
        .data = (void *)ext_csd,
        .timeout_ms = SDMMC_WRITE_CMD_TIMEOUT_MS,
    };
    err = sdmmc_send_cmd(card, &cmd_ext_csd);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("err ext_csd: %d\n", err);
    }
#if 0    
    ZYP_DEBUG_VERIFY_CASE("ext_csd: \n");
    for (size_t i = 0; i < EXT_CSD_MMC_SIZE; i++)
    {
        ZYP_DEBUG_VERIFY_CASE("%02x ", card->ext_csd[i]);
    }
    ZYP_DEBUG_VERIFY_CASE("\n");
#endif
    ZYP_DEBUG_VERIFY_CASE(" ext_csd[%d]: %d\n", BOOT_WP, ext_csd[BOOT_WP]);
    if (ext_csd[BOOT_WP] != 0)
    {
        ZYP_DEBUG_VERIFY_CASE(" INIT MUST 0\n");
        return ESP_FAIL;
    }
    if (ext_csd[BOOT_WP_STATUS] != 0)
    {
        ZYP_DEBUG_VERIFY_CASE(" INIT MUST 0\n");
        return ESP_FAIL;
    }

    // if ((ext_csd[BOOT_WP] == 0) && (ext_csd[BOOT_WP_STATUS] == 0) || (ext_csd[BOOT_WP_STATUS] == 0x0A && ext_csd[BOOT_WP_STATUS] == 0X04))
    // {
    //     /* code */
    // }
    // else
    // {

    // }

    /// cmd6 switch boot1 partion
    ZYP_DEBUG_VERIFY_CASE("-------------switch boot1-------------\n");
    sdmmc_command_t cmd_switch = {
        .opcode = MMC_SWITCH,
        .arg = 0x03B30100,
        .flags = SCF_RSP_R1B | SCF_CMD_AC | SCF_WAIT_BUSY,
    };
    err = sdmmc_send_cmd(card, &cmd_switch);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("err switch: %d\n", err);
    }

    size_t _total_blocks = 1;
    /// cmd18 read 1 block should be zear
    uint8_t *buffer_r = (uint8_t *)heap_caps_malloc(EXT_CSD_MMC_SIZE * 1, MALLOC_CAP_DMA);

    requestbuffer->cmdId = MMC_READ_BLOCK_MULTIPLE;
    requestbuffer->cmdParm = 0;
    sdmmc_command_t cmd_read_block_cmd = {
        .opcode = MMC_READ_BLOCK_MULTIPLE,
        .flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_WAIT_BUSY, /// .flags recacultor  in zyp_sdmmc_read_sectors_dma
        .blklen = EXT_CSD_MMC_SIZE,
        .datalen = _total_blocks * EXT_CSD_MMC_SIZE,
        .data = (void *)buffer_r,
        .timeout_ms = SDMMC_WRITE_CMD_TIMEOUT_MS,
    };
    err = zyp_sendReadCmd(&cmd_read_block_cmd, card, requestbuffer, (unsigned int *)buffer_r, 0, _total_blocks); /// param  start_block, no use
    if (err != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("err write: %s\n", esp_err_to_name(err));
    }
    unsigned char cmpare_buffer[EXT_CSD_MMC_SIZE] = {0};
    if (memcmp(buffer_r, (void *)cmpare_buffer, EXT_CSD_MMC_SIZE) != 0)
    {
        ZYP_DEBUG_VERIFY_CASE("------------- err deaflut  shloud be all 0-------------\n");
        return ESP_FAIL;
    }

    /// cmd6 add BOOT PERM_WP
    ZYP_DEBUG_VERIFY_CASE("-------------switch BOOT_WP-------------\n");
    sdmmc_command_t cmd_switch2 = {
        .opcode = MMC_SWITCH,
        .arg = 0x03AD8400,
        .flags = SCF_RSP_R1B | SCF_CMD_AC | SCF_WAIT_BUSY,
    };
    err = sdmmc_send_cmd(card, &cmd_switch2);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("err switch: %d\n", err);
    }

    /// cmd8 cheack ext_csd  173 174
    sdmmc_command_t cmd_ext_csd2 = {
        .opcode = MMC_SEND_EXT_CSD,
        .flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_CMD_READ,
        .datalen = EXT_CSD_MMC_SIZE,
        .blklen = EXT_CSD_MMC_SIZE,
        .data = (void *)ext_csd,
    };
    err = sdmmc_send_cmd(card, &cmd_ext_csd2);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("err ext_csd: %d\n", err);
    }

    if (ext_csd[BOOT_WP] != 0x84)
    {
        ZYP_DEBUG_VERIFY_CASE("-------------err BOOT_WP value must be 0x84  -------------\n");
        return ESP_FAIL;
    }
    if (ext_csd[BOOT_WP_STATUS] != 0x02)
    {
        ZYP_DEBUG_VERIFY_CASE("-------------err BOOT_WP_STATUS value must be 0x02  -------------\n");
        return ESP_FAIL;
    }
    /// write resp is 09
    memset(ext_csd, 0x5A, EXT_CSD_MMC_SIZE);

    /// cmd13 resp is  00040900
    requestbuffer->cmdId = MMC_WRITE_BLOCK_MULTIPLE;
    requestbuffer->cmdParm = 0;
    zyp_mmc_write_sectors(cmd, card, requestbuffer, ext_csd, 0, 1);
    if (cmd->response[0] != 0x0009000)
    {
        ZYP_DEBUG_VERIFY_CASE("-------------err write  -------------\n");
        return ESP_FAIL;
    }
    /// cmd13 check resp is 00040900
    sdmmc_command_t cmd_state = {
        .opcode = MMC_SEND_STATUS,
        .arg = MMC_ARG_RCA(card->rca),
        .flags = SCF_CMD_AC | SCF_RSP_R1};
    err = sdmmc_send_cmd(card, &cmd_state);
    if (cmd_state.response[0] != 0x00040900)
    {
        ZYP_DEBUG_VERIFY_CASE("-------------err resp is   -------------\n");
        return ESP_FAIL;
    }

    /// switch boot2  partion
    sdmmc_command_t cmd_switch3 = {
        .opcode = MMC_SWITCH,
        .arg = 0x03B30200,
        .flags = SCF_RSP_R1B | SCF_CMD_AC | SCF_WAIT_BUSY,
    };
    err = sdmmc_send_cmd(card, &cmd_switch3);
    if (err != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("err switch: %d\n", err);
    }

    /// wite
    memset(ext_csd, 0x5B, EXT_CSD_MMC_SIZE);
    requestbuffer->cmdId = MMC_WRITE_BLOCK_MULTIPLE;
    requestbuffer->cmdParm = 0;
    zyp_mmc_write_sectors(cmd, card, requestbuffer, ext_csd, 0, 1);
    if (cmd->response[0] != 0x0009000)
    {
        ZYP_DEBUG_VERIFY_CASE("-------------err write  -------------\n");
        return ESP_FAIL;
    }

    /// read
    memset(buffer_r, 0, EXT_CSD_MMC_SIZE);
    requestbuffer->cmdId = MMC_READ_BLOCK_MULTIPLE;
    requestbuffer->cmdParm = 0;
    sdmmc_command_t cmd_read_block_cmd_s = {
        .opcode = MMC_READ_BLOCK_MULTIPLE,
        .flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_WAIT_BUSY, /// .flags recacultor  in zyp_sdmmc_read_sectors_dma
        .blklen = EXT_CSD_MMC_SIZE,
        .datalen = _total_blocks * EXT_CSD_MMC_SIZE,
        .data = (void *)buffer_r,
        .timeout_ms = SDMMC_WRITE_CMD_TIMEOUT_MS,
    };
    err = zyp_sendReadCmd(&cmd_read_block_cmd_s, card, requestbuffer, (unsigned int *)buffer_r, 0, _total_blocks); /// param  start_block, no use
    if (err != ESP_OK)
    {
        ZYP_DEBUG_VERIFY_CASE("err write: %s\n", esp_err_to_name(err));
        return ESP_FAIL;
    }

    memset(cmpare_buffer, 0x5B, EXT_CSD_MMC_SIZE);
    if (memcmp(cmpare_buffer, buffer_r, EXT_CSD_MMC_SIZE) != 0)
    {
        ZYP_DEBUG_VERIFY_CASE("------------- err deaflut  shloud be all 0-------------\n");
        return ESP_FAIL;
    }
    /// power on emmc and reset host bus fre

    /// cheack ext_csd  173 04  174 0A

    /// cmd6 0x03B30100 slecte boot1 partion

    /// cmd25 write 5A resp09 then cmd13 040900

    /// switch boot2 partion

    /// cheack write read

    if (buffer_r != NULL)
    {
        heap_caps_free(buffer_r);
    }
    if (ext_csd != NULL)
    {
        heap_caps_free(ext_csd);
    }
    return ESP_OK;
}

/// @brief
/// @param cmd
/// @param card
/// @param requestbuffer
/// @param responsebuffer
/// @param total_blocks
/// @param chunk_blocks evertime write  block cnt
/// @param buffer_size   每次写的块size，using malloc
/// @return
esp_err_t zyp_write_X_partion_custom_block(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer,
                                           size_t total_blocks, size_t chunk_blocks, size_t buffer_size)
{
    /// Subcontracting writing
    esp_err_t err = ESP_OK;
    // const size_t total_blocks = 1024 * 1024 / 2; // 1MB (2048个512block)
    // const size_t chunk_blocks = 128;              ///一次写128block  64KB
    // const size_t buffer_size = chunk_blocks * EXT_CSD_MMC_SIZE;

    uint8_t *write_buffer = (uint8_t *)heap_caps_malloc(buffer_size, MALLOC_CAP_DMA);
    if (write_buffer == NULL)
    {
        return ESP_ERR_NO_MEM;
    }
    memset(requestbuffer, 0, sizeof(struct RequestBuffer));
    ZYP_DEBUG("%d\n", __LINE__);
    requestbuffer->startBit = 0; /// construct cmd25 requestbuffer
    requestbuffer->requestDirection = 0;
    requestbuffer->cmdId = MMC_WRITE_BLOCK_MULTIPLE;
    requestbuffer->rwFlag = 0x02;
    requestbuffer->respType = 0x01;
    requestbuffer->endBit = 0x7A;
    cmd->flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_WAIT_BUSY;

    for (size_t written_blocks = 0; written_blocks < total_blocks; written_blocks += chunk_blocks)
    {
        size_t blocks_to_write = (written_blocks + chunk_blocks <= total_blocks) ? chunk_blocks : (total_blocks - written_blocks);

        requestbuffer->cmdParm = written_blocks;

        memset(write_buffer, 0x5A, blocks_to_write * EXT_CSD_MMC_SIZE);

        err = zyp_mmc_write_sectors(cmd, card, requestbuffer, write_buffer,
                                    written_blocks, blocks_to_write);
        if (err != ESP_OK)
        {
            break;
        }
    }
    heap_caps_free(write_buffer);

    if (err == ESP_OK)
    {
        zyp_handle_mmc_cmd_response(cmd, requestbuffer, responsebuffer, false);
    }
    else
    {
        zyp_handle_mmc_cmd_response(cmd, requestbuffer, responsebuffer, true);
    }

    return err;
}

esp_err_t zyp_write_X_partion_1MB(sdmmc_command_t *cmd, sdmmc_card_t *card, struct RequestBuffer *requestbuffer, struct ResponseBuffer *responsebuffer)
{
#if 0   
    esp_err_t err;
    ZYP_DEBUG("%d\n",__LINE__);
    size_t buffer_size = EXT_CSD_MMC_SIZE * 2 * 1024; /// 1MB
    ZYP_DEBUG("%d\n",__LINE__);
    uint8_t *write_buffer = (uint8_t *)heap_caps_malloc(buffer_size, MALLOC_CAP_DMA);
    ZYP_DEBUG("%d\n",__LINE__);
    // memset(write_buffer, 0x5A, buffer_size);
    memset(requestbuffer, 0, sizeof(struct RequestBuffer));
    ZYP_DEBUG("%d\n",__LINE__);
    requestbuffer->startBit = 0;
    requestbuffer->requestDirection=0;
    requestbuffer->cmdId = MMC_WRITE_BLOCK_MULTIPLE;
    requestbuffer->cmdParm = 0;
    requestbuffer->rwFlag = 0x02;
    requestbuffer->respType = 0x01;
    requestbuffer->endBit = 0x7A;

    cmd->flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_WAIT_BUSY;
    err = zyp_mmc_write_sectors(cmd, card, requestbuffer, write_buffer, 0, 2 * 1024);         ///cmd25+cmd12  enter else
    ZYP_DEBUG("%d\n",__LINE__);
    ZYP_DEBUG_MMC("err:%s\n", esp_err_to_name(err));
    if (!err)
    {
        zyp_handle_mmc_cmd_response(cmd, requestbuffer, responsebuffer, false);
    }
    else
    {
        zyp_handle_mmc_cmd_response(cmd, requestbuffer, responsebuffer, true);
    }
    if (write_buffer != NULL)
    {
        heap_caps_free(write_buffer);
    }

    return err;
#endif

    /// Subcontracting writing
    esp_err_t err = ESP_OK;
    const size_t total_blocks = 1024 * 1024 / 2; // 1MB (2048个512block)
    const size_t chunk_blocks = 128;             /// 一次写128block  64KB
    const size_t buffer_size = chunk_blocks * EXT_CSD_MMC_SIZE;

    uint8_t *write_buffer = (uint8_t *)heap_caps_malloc(buffer_size, MALLOC_CAP_DMA);
    if (write_buffer == NULL)
    {
        return ESP_ERR_NO_MEM;
    }

    memset(requestbuffer, 0, sizeof(struct RequestBuffer));
    ZYP_DEBUG("%d\n", __LINE__);
    requestbuffer->startBit = 0; /// construct cmd25 requestbuffer
    requestbuffer->requestDirection = 0;
    requestbuffer->cmdId = MMC_WRITE_BLOCK_MULTIPLE;
    requestbuffer->rwFlag = 0x02;
    requestbuffer->respType = 0x01;
    requestbuffer->endBit = 0x7A;
    cmd->flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_WAIT_BUSY;

    for (size_t written_blocks = 0; written_blocks < total_blocks; written_blocks += chunk_blocks)
    {
        size_t blocks_to_write = (written_blocks + chunk_blocks <= total_blocks) ? chunk_blocks : (total_blocks - written_blocks);

        requestbuffer->cmdParm = written_blocks;

        memset(write_buffer, 0x5A, blocks_to_write * EXT_CSD_MMC_SIZE);

        err = zyp_mmc_write_sectors(cmd, card, requestbuffer, write_buffer,
                                    written_blocks, blocks_to_write);
        if (err != ESP_OK)
        {
            break;
        }
    }

    heap_caps_free(write_buffer);

    if (err == ESP_OK)
    {
        zyp_handle_mmc_cmd_response(cmd, requestbuffer, responsebuffer, false);
    }
    else
    {
        zyp_handle_mmc_cmd_response(cmd, requestbuffer, responsebuffer, true);
    }

    return err;
}

#if 0
esp_err_t zyp_mmc_erase_sectors(sdmmc_card_t *card, size_t start_sector, size_t sector_count, sdmmc_erase_arg_t arg)
{

    if (sector_count == 0)
    {
        return ESP_OK;
    }

    // if (start_sector + sector_count > card->csd.capacity) {
    //     return ESP_ERR_INVALID_SIZE;
    // }

    uint32_t cmd38_arg;
    if (arg == SDMMC_ERASE_ARG)
    {
        cmd38_arg = SDMMC_MMC_TRIM_ARG;
    }
    else
    {
        cmd38_arg = SDMMC_MMC_DISCARD_ARG;
    }

    /* validate the CMD38 argument against card supported features */
    if ((cmd38_arg == SDMMC_MMC_TRIM_ARG) && (sdmmc_can_trim(card) != ESP_OK))
    {
        return ESP_ERR_NOT_SUPPORTED;
    }
    if ((cmd38_arg == SDMMC_MMC_DISCARD_ARG) && (sdmmc_can_discard(card) != ESP_OK))
    {
        return ESP_ERR_NOT_SUPPORTED;
    }

    /* default as block unit address */
    size_t addr_unit_mult = 1;

    // if (!(card->ocr & SD_OCR_SDHC_CAP))
    // {
    //     addr_unit_mult = card->csd.sector_size;
    // }

    /* prepare command to set the start address */
    sdmmc_command_t cmd = {
        .flags = SCF_CMD_AC | SCF_RSP_R1 | SCF_WAIT_BUSY,
        .opcode = MMC_ERASE_GROUP_START,
        .arg = (start_sector * addr_unit_mult),
    };

    esp_err_t err = sdmmc_send_cmd(card, &cmd);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "%s: sdmmc_send_cmd (ERASE_GROUP_START) returned 0x%x", __func__, err);
        return err;
    }

    /* prepare command to set the end address */
    cmd.opcode = card->is_mmc ? MMC_ERASE_GROUP_END : SD_ERASE_GROUP_END;
    cmd.arg = ((start_sector + (sector_count - 1)) * addr_unit_mult);

    err = sdmmc_send_cmd(card, &cmd);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "%s: sdmmc_send_cmd (ERASE_GROUP_END) returned 0x%x", __func__, err);
        return err;
    }

    /* issue erase command */
    memset((void *)&cmd, 0, sizeof(sdmmc_command_t));
    cmd.flags = SCF_CMD_AC | SCF_RSP_R1B | SCF_WAIT_BUSY;
    cmd.opcode = MMC_ERASE;
    cmd.arg = cmd38_arg;
    cmd.timeout_ms = sdmmc_get_erase_timeout_ms(card, cmd38_arg, sector_count * card->csd.sector_size / 1024);

    err = sdmmc_send_cmd(card, &cmd);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "%s: sdmmc_send_cmd (ERASE) returned 0x%x", __func__, err);
        return err;
    }

    if (host_is_spi(card))
    {
        uint32_t status;
        err = sdmmc_send_cmd_send_status(card, &status);
        if (err != ESP_OK)
        {
            ESP_LOGE(TAG, "%s: sdmmc_send_cmd_send_status returned 0x%x", __func__, err);
            return err;
        }
        if (status != 0)
        {
            ESP_LOGE(TAG, "%s: card status indicates an error after erase operation: r2=0x%04x",
                     __func__, status);
            return ESP_ERR_INVALID_RESPONSE;
        }
    }

    return ESP_OK;
}
#endif

#if IS_FILE_DEBUG
esp_err_t zyp_debugbin_flow(sdmmc_card_t *card, uint32_t fileIndex)
{
    uint8_t *file_start = psram_base + fileIndex * FILE_SLOT_SIZE;
    uint32_t condition = *(uint32_t *)file_start;
    if (condition != DUGBIN_FILE_START_FLAG)
    {
        return ESP_FAIL;
    }

    ZYP_DEBUG_MMC("------------zyp_debugbin_flow begain-------\n");
    char *tag_virgin = "debugbin_flow";
    esp_err_t err;
    uint32_t cmd61_param = 0x20464C4C;
    uint32_t cmd6_set_bus_8bit_sdr = 0x03B70200;
    uint32_t cmd6_set_high_speed = 0x03B90100;
    uint32_t cmd60_parm1 = 0x03000001;
    uint32_t cmd60_parm2 = 0x00b04000;
#if IS_NEED_HARD_CODE
    uint8_t *llf_addr = (uint8_t *)SAVA_LLF_FILE_STARTADDR;
#endif

    uint8_t *debugbin_addr = file_start;
    uint32_t cmd25_parm = 0;

    uint32_t vcmd60_deploy_exec = 0x08000002;
    uint32_t vcmd60_dnld_addr = 0x00b04000;
    uint32_t vcmd60_dnld_start_address = 00000001;
    uint32_t *cmd13_repsonce0 = NULL;

#if ENABLE_CMD60_CMD61
    /// #enable device enter card initial mode and continue running in rom mode(avoid to run into main fw)
    // zyp_send_cmd60_cmd61_random(card, cmd61_param, MMC_APP_CMD61);
    ZYP_Stirng_MMC_CHECK_CMD(zyp_send_cmd60_cmd61_random(card, cmd61_param, MMC_APP_CMD61), err, tag_virgin, "the first cmd61 err");
    ZYP_Stirng_MMC_CHECK_CMD(zyp_send_cmd60_cmd61_random(card, cmd61_param, MMC_APP_CMD61), err, tag_virgin, "the second cmd61 err ");
#endif
    ////#enter transfer mode
    ZYP_Stirng_MMC_CHECK_CMD(zyp_cmd0_go_idle_state(card), err, tag_virgin, "cmd0 err");
    ZYP_DEBUG_MMC("card->is_mmc :%d\n", card->is_mmc);
    card->is_mmc = 1; /// must keep or cmd3 send twice err?  cmd3 hava jujy  card->is_mmc
    ZYP_Stirng_MMC_CHECK_CMD(zyp_mmc_send_cmd_send_op_cond(card), err, tag_virgin, "cmd1 err");

    ZYP_Stirng_MMC_CHECK_CMD(zyp_sdmmc_init_cid(card), err, tag_virgin, "cmd2 err");

    ZYP_Stirng_MMC_CHECK_CMD(zyp_sdmmc_send_cmd_set_relative_addr(card, &card->rca), err, tag_virgin, "cmd3 err"); /// rca cmd1

    ZYP_Stirng_MMC_CHECK_CMD(zyp_sdmmc_send_cmd_send_csd(card, &card->csd), err, tag_virgin, "cmd9 err");

    ZYP_DEBUG_MMC("CMD9 after card->rca :%d\n", card->rca);
    card->rca = 1;
    ZYP_Stirng_MMC_CHECK_CMD(zyp_mmc_send_cmd_select_card(card, card->rca), err, TAG, "cmd7 err");

    /// #check register
    ZYP_Stirng_MMC_CHECK_CMD(sdmmc_init_mmc_read_ext_csd(card), err, tag_virgin, "cmd8 err");
    vTaskDelay(pdMS_TO_TICKS(200)); /// if not why

#if IS_ENABLE_8BIT_50M
    errmsage = "cmd6_set_bus_8bit_sdr err";
    ZYP_Stirng_MMC_CHECK_CMD(zyp_switch_cmd(card, cmd6_set_bus_8bit_sdr), err, tag_virgin, "cmd6_set_bus_8bit_sdr err");

    errmsage = "cmd6_set_high_speed err";
    ZYP_Stirng_MMC_CHECK_CMD(zyp_switch_cmd(card, cmd6_set_high_speed), err, tag_virgin, "cmd6_set_high_speed err");
#endif

#if IS_ENABLE_SDR_8BIT_40MHZ
    errmsage = THE_CMD6_SDR_8BIT_MODE_ERR;
    err = zyp_sdmmc_configure_bus_fre_mode(card, SDMMC_FREQ_HIGHSPEED, 8, 0); /// 8bit sdr  40MHZ      though test host switch max is 40MHZ ，despite switch  SDMMC_FREQ_52M
    if (err)
    {
        return err;
    }
#endif

#if ENABLE_CMD60_CMD61
    /// indicates that this is a write sector data cmd with still a subsequent cmd60
    ZYP_Stirng_MMC_CHECK_CMD(zyp_send_cmd60_cmd61_random(card, cmd60_parm1, MMC_APP_CMD60), err, tag_virgin, "cmd60_parm1 err");

    /// indicates that these data will be written begin at ram address 0b04000(data buffer area in sram)
    ZYP_Stirng_MMC_CHECK_CMD(zyp_send_cmd60_cmd61_random(card, cmd60_parm2, MMC_APP_CMD60), err, tag_virgin, "cmd60_parm2 err");
#endif
    /// write data to the specified address above, with cmd12 to end
#if VIGINAL_MODE_HARD_STARTBIT_NO_FILE_SIZE
    if (virigin_file_size_t.debug_file_size != 0)
    {
        ZYP_DEBUG("virigin_file_size_t.debug_file_size:%d\n", virigin_file_size_t.debug_file_size);
        ZYP_Stirng_MMC_CHECK_CMD(zyp_write_psram_to_emmc(card, debugbin_addr, virigin_file_size_t.debug_file_size, cmd25_parm), err, tag_virgin, "write_debugbin err");
    }
#endif

    vTaskDelay(pdMS_TO_TICKS(500));
#if ENABLE_CMD60_CMD61
    /// # set execute mode to VCMD60_DEPLOY_AND_EXEC
    ZYP_Stirng_MMC_CHECK_CMD(zyp_send_cmd60_cmd61_random(card, vcmd60_deploy_exec, MMC_APP_CMD60), err, tag_virgin, "vcmd60_deploy_exec err");
    /// # set dnld binary source address
    ZYP_Stirng_MMC_CHECK_CMD(zyp_send_cmd60_cmd61_random(card, vcmd60_dnld_addr, MMC_APP_CMD60), err, tag_virgin, "vcmd60_dnld_addr err");
    /// # copy dnld from dbuf and jump to dnld start address
    ZYP_Stirng_MMC_CHECK_CMD(zyp_send_cmd60_cmd61_random(card, vcmd60_dnld_start_address, MMC_APP_CMD60), err, tag_virgin, "vcmd60_dnld_start_address err");
#endif
    return ESP_OK;
}

#endif

///
esp_err_t zyp_virgin_flow(sdmmc_card_t *card, uint32_t fileIndex)
{
    if (!psram_base)
    {
        ESP_LOGE(TAG, "psram_base not allocated");
        return ESP_FAIL;
    }
    uint8_t *file_start = psram_base + fileIndex * FILE_SLOT_SIZE; /// now must recive third file  done

    uint32_t condition = *(uint32_t *)file_start;
    ZYP_DEBUG_MMC("current_file_index :%ld\n", current_file_index);
    ZYP_DEBUG_MMC("fileIndex :%ld\n", fileIndex);

    ZYP_DEBUG_MMC("addr psram_base:%p, third file addr: %p\n", psram_base, file_start);
    ZYP_DEBUG_MMC("Condition: %08lx\n", condition);

    if (condition == LLF_FILE_START_4BIT || condition == DNLD_FILE_START_4BIT || condition == MAIN_FILE_START_4BIT)
    {

        /* code */
        ZYP_DEBUG_MMC("------------zyp_virgin_flow begain-------\n");

        char *tag_virgin = "virgin_flow";
        esp_err_t err;
        uint32_t cmd61_param = 0x20464C4C;
        // uint32_t cmd6_set_bus_8bit_sdr = 0x03B70200;
        // uint32_t cmd6_set_high_speed = 0x03B90100;
        uint32_t cmd60_parm1 = 0x03000001;
        uint32_t cmd60_parm2 = 0x00b04000;
#if IS_NEED_HARD_CODE
        uint8_t *llf_addr = (uint8_t *)SAVA_LLF_FILE_STARTADDR;
#endif
        // uint8_t *llf_addr =file_start;
        uint8_t *dnld_addr = file_start - DNLD_FILE * FILE_SLOT_SIZE;
        uint8_t *main_addr = file_start;
        uint8_t *llf_addr = file_start - MAIN_FILE * FILE_SLOT_SIZE;

        uint32_t cmd25_parm = 0;

        uint32_t vcmd60_deploy_exec = 0x08000002;
        uint32_t vcmd60_dnld_addr = 0x00b04000;
        uint32_t vcmd60_dnld_start_address = 00000001;
        uint32_t *cmd13_repsonce0 = NULL;

        uint32_t cmd6_parm_ffu_mode = 0x031E0100;
        uint32_t cmd6_parm_install = 0x031D0100;
        uint32_t cmd6_set_bus_8bit_sdr = 0X03B70200;
        uint32_t cmd6_set_high_speed = 0X03B90100;

#if IS_NEED_HARD_CODE
        uint8_t *dnld_addr = (uint8_t *)SAVA_DNLD_FILE_STARTADDR;
        uint8_t *main_addr = (uint8_t *)SAVA_MAIN_FILE_STARTADDR;
#endif

#if ENABLE_FORMAT_STRING_TYPE

#if ENABLE_CMD60_CMD61
        /// #enable device enter card initial mode and continue running in rom mode(avoid to run into main fw)
        errmsage = THE_FIRST_CMD61_ERR;
        // zyp_send_cmd60_cmd61_random(card, cmd61_param, MMC_APP_CMD61);
        ZYP_Stirng_MMC_CHECK_CMD(zyp_send_cmd60_cmd61_random(card, cmd61_param, MMC_APP_CMD61), err, tag_virgin, "the first cmd61 err");
#if IS_ENBALE_FactoryModeProcess
        zyp_construct_vriginal_process_message_fream_to_send(&factory_mode_process_t, THE_FIRST_CMD61, MMC_APP_CMD61, cmd61_param); /// process
#endif
        errmsage = THE_SECOND_CMD61_ERR;
        ZYP_Stirng_MMC_CHECK_CMD(zyp_send_cmd60_cmd61_random(card, cmd61_param, MMC_APP_CMD61), err, tag_virgin, "the second cmd61 err ");
#if IS_ENBALE_FactoryModeProcess
        zyp_construct_vriginal_process_message_fream_to_send(&factory_mode_process_t, THE_SECOND_CMD61, MMC_APP_CMD61, cmd61_param);
#endif
#endif

        ////#enter transfer mode
        errmsage = THE_INIT_GO_IDLE_ERR;
        ZYP_Stirng_MMC_CHECK_CMD(zyp_cmd0_go_idle_state(card), err, tag_virgin, "cmd0 err");
        ZYP_DEBUG_MMC("card->is_mmc :%d\n", card->is_mmc);
        card->is_mmc = 1; /// must keep or cmd3 send twice err?  cmd3 hava jujy  card->is_mmc

#if 1
        slot_config.width = BUS_WITH_1BIT;
        ZYP_SDMMC_CHECK_CMD(sdmmc_host_init_slot(card->host.slot, &slot_config), err, TAG, "host_init_slot err");
        card->host.set_bus_width(card->host.slot, BUS_WITH_1BIT);
#endif
        ZYP_SDMMC_CHECK_CMD(sdmmc_host_set_card_clk(card->host.slot, SDMMC_FREQ_PROBING), err, TAG, " switch host clk err");
        ZYP_SDMMC_CHECK_CMD(sdmmc_host_set_bus_width(card->host.slot, BUS_WITH_1BIT), err, TAG, " switch host bus err");
        ZYP_SDMMC_CHECK_CMD(sdmmc_host_set_bus_ddr_mode(card->host.slot, 0), err, TAG, " switch host ddr err");

#if 0
        err = card->host.set_cclk_always_on(card->host.slot, true);
        if (err != ESP_OK) {
            ESP_LOGE(TAG, "%s: set_cclk_always_on (1) err=0x%x", __func__, err);
            return err;
        }
#endif

#if IS_ENBALE_FactoryModeProcess
        zyp_construct_vriginal_process_message_fream_to_send(&factory_mode_process_t, THE_INIT_GO_IDLE, MMC_GO_IDLE_STATE, MMC_PARME_ZEARO);
#endif
        errmsage = THE_INIT_OP_COND_ERR;
        ZYP_Stirng_MMC_CHECK_CMD(zyp_mmc_send_cmd_send_op_cond(card), err, tag_virgin, "cmd1 err");
#if IS_ENBALE_FactoryModeProcess
        zyp_construct_vriginal_process_message_fream_to_send(&factory_mode_process_t, THE_INIT_OP_COND, MMC_SEND_OP_COND, MMC_GO_IDLE_STATE_PARAMETER);
#endif
        errmsage = THE_INTI_CID_ERR;
        ZYP_Stirng_MMC_CHECK_CMD(zyp_sdmmc_init_cid(card), err, tag_virgin, "cmd2 err");
#if IS_ENBALE_FactoryModeProcess
        zyp_construct_vriginal_process_message_fream_to_send(&factory_mode_process_t, THE_INTI_CID, MMC_ALL_SEND_CID, MMC_PARME_ZEARO);
#endif
        errmsage = THE_INIT_SET_RELATIVE_ERR;
        ZYP_Stirng_MMC_CHECK_CMD(zyp_sdmmc_send_cmd_set_relative_addr(card, &card->rca), err, tag_virgin, "cmd3 err"); /// rca cmd1
#if IS_ENBALE_FactoryModeProcess
        zyp_construct_vriginal_process_message_fream_to_send(&factory_mode_process_t, THE_INIT_SET_RELATIVE, MMC_SET_RELATIVE_ADDR, MMC_PARME_ZEARO);
#endif
        errmsage = THE_INIT_SEND_CSD_ERR;
        ZYP_Stirng_MMC_CHECK_CMD(zyp_sdmmc_send_cmd_send_csd(card, &card->csd), err, tag_virgin, "cmd9 err");
#if IS_ENBALE_FactoryModeProcess
        zyp_construct_vriginal_process_message_fream_to_send(&factory_mode_process_t, THE_INIT_SEND_CSD, MMC_SEND_CSD, MMC_PARME_ZEARO);
#endif

        ZYP_DEBUG_MMC("CMD9 after card->rca :%d\n", card->rca);
        card->rca = 1;
        errmsage = THE_INIT_SLECTE_CARD_ERR;
        ZYP_Stirng_MMC_CHECK_CMD(zyp_mmc_send_cmd_select_card(card, card->rca), err, TAG, "cmd7 err");
#if IS_ENBALE_FactoryModeProcess
        zyp_construct_vriginal_process_message_fream_to_send(&factory_mode_process_t, THE_INIT_SLECTE_CARD, MMC_SELECT_CARD, RCA_HARDVALUE);
#endif
        /// #check register
        errmsage = THE_INIT_READ_EXTCSD_ERR;
        ZYP_Stirng_MMC_CHECK_CMD(sdmmc_init_mmc_read_ext_csd(card), err, tag_virgin, "cmd8 err");
        vTaskDelay(pdMS_TO_TICKS(200)); /// if not why
#if IS_ENBALE_FactoryModeProcess
        zyp_construct_vriginal_process_message_fream_to_send(&factory_mode_process_t, THE_INIT_READ_EXTCSD, MMC_SEND_EXT_CSD, MMC_PARME_ZEARO);
#endif

#if 0
        zyp_switch_cmd(card, cmd6_set_bus_8bit_sdr);
        zyp_switch_cmd(card, cmd6_set_high_speed);
        zyp_sdmmc_configure_bus_fre_mode(card, SDMMC_FREQ_HIGHSPEED, 8, 0);

#if IS_ENABLE_8BIT_50M
        errmsage = "cmd6_set_bus_8bit_sdr err";
        ZYP_Stirng_MMC_CHECK_CMD(zyp_switch_cmd(card, cmd6_set_bus_8bit_sdr), err, tag_virgin, "cmd6_set_bus_8bit_sdr err");

        errmsage = "cmd6_set_high_speed err";
        ZYP_Stirng_MMC_CHECK_CMD(zyp_switch_cmd(card, cmd6_set_high_speed), err, tag_virgin, "cmd6_set_high_speed err");
#endif

#if IS_ENABLE_SDR_8BIT_40MHZ
        errmsage = THE_CMD6_SDR_8BIT_MODE_ERR;
        err = zyp_sdmmc_configure_bus_fre_mode(card, SDMMC_FREQ_HIGHSPEED, 8, 0); /// 8bit sdr  40MHZ      though test host switch max is 40MHZ ，despite switch  SDMMC_FREQ_52M
        if (err)
        {
            return err;
        }
#endif

#endif

#if ENABLE_CMD60_CMD61
        /// indicates that this is a write sector data cmd with still a subsequent cmd60
        errmsage = THE_CMD60_PRAME1_ERR;
        ZYP_Stirng_MMC_CHECK_CMD(zyp_send_cmd60_cmd61_random(card, cmd60_parm1, MMC_APP_CMD60), err, tag_virgin, "cmd60_parm1 err");
#if IS_ENBALE_FactoryModeProcess
        zyp_construct_vriginal_process_message_fream_to_send(&factory_mode_process_t, THE_CMD60_PRAME1, MMC_APP_CMD60, cmd60_parm1);
#endif

        /// indicates that these data will be written begin at ram address 0b04000(data buffer area in sram)
        errmsage = THE_CMD60_PRAME2_ERR;
        ZYP_Stirng_MMC_CHECK_CMD(zyp_send_cmd60_cmd61_random(card, cmd60_parm2, MMC_APP_CMD60), err, tag_virgin, "cmd60_parm2 err");
#if IS_ENBALE_FactoryModeProcess
        zyp_construct_vriginal_process_message_fream_to_send(&factory_mode_process_t, THE_CMD60_PRAME2, MMC_APP_CMD60, cmd60_parm2);
#endif

#endif
        /// write data to the specified address above, with cmd12 to end
        errmsage = THE_WRITE_LLF_ERR;
#if VIGINAL_MODE_HARD_STARTBIT_NO_FILE_SIZE
        if (virigin_file_size_t.llf_file_size != 0)
        {
            ZYP_DEBUG("virigin_file_size_t.llf_file_size:%d\n", virigin_file_size_t.llf_file_size);
            ZYP_Stirng_MMC_CHECK_CMD(zyp_write_psram_to_emmc(card, llf_addr, virigin_file_size_t.llf_file_size, cmd25_parm), err, tag_virgin, "write_llf err");
        }
#endif

#if !VIGINAL_MODE_HARD_STARTBIT_NO_FILE_SIZE
        ZYP_Stirng_MMC_CHECK_CMD(zyp_write_psram_to_emmc(card, llf_addr, LLF_FILE_SIZE, cmd25_parm), err, tag_virgin, "write_llf err");
#endif
        //   ZYP_SDMMC_CHECK_CMD(zyp_write_psram_to_emmc(card,llf_addr,LLF_FILE_SIZE,cmd25_parm),err,tag_virgin,"write_llf err %s",esp_err_to_name(err));
        // vTaskDelay(pdMS_TO_TICKS(200));
        vTaskDelay(pdMS_TO_TICKS(500));
#if IS_ENBALE_FactoryModeProcess
        zyp_construct_vriginal_process_message_fream_to_send(&factory_mode_process_t, THE_WRITE_LLF, MMC_WRITE_BLOCK_MULTIPLE, cmd25_parm);
#endif
#if ENABLE_CMD60_CMD61
        /// # set execute mode to VCMD60_DEPLOY_AND_EXEC
        errmsage = THE_VCMD60_DEPLOY_EXEC_ERR;
        ZYP_Stirng_MMC_CHECK_CMD(zyp_send_cmd60_cmd61_random(card, vcmd60_deploy_exec, MMC_APP_CMD60), err, tag_virgin, "vcmd60_deploy_exec err");
#if IS_ENBALE_FactoryModeProcess
        zyp_construct_vriginal_process_message_fream_to_send(&factory_mode_process_t, THE_VCMD60_DEPLOY_EXEC, MMC_APP_CMD60, vcmd60_deploy_exec);
#endif
        /// # set dnld binary source address
        errmsage = THE_VCMD60_DNLD_ADDR_ERR;
        ZYP_Stirng_MMC_CHECK_CMD(zyp_send_cmd60_cmd61_random(card, vcmd60_dnld_addr, MMC_APP_CMD60), err, tag_virgin, "vcmd60_dnld_addr err");
#if IS_ENBALE_FactoryModeProcess
        zyp_construct_vriginal_process_message_fream_to_send(&factory_mode_process_t, THE_VCMD60_DEPLOY_EXEC, MMC_APP_CMD60, vcmd60_dnld_addr);
#endif

        /// # copy dnld from dbuf and jump to dnld start address
        errmsage = THE_VCMD60_DNLD_STARTADDR_ERR;
        ZYP_Stirng_MMC_CHECK_CMD(zyp_send_cmd60_cmd61_random(card, vcmd60_dnld_start_address, MMC_APP_CMD60), err, tag_virgin, "vcmd60_dnld_start_address err");
#if IS_ENBALE_FactoryModeProcess
        zyp_construct_vriginal_process_message_fream_to_send(&factory_mode_process_t, THE_VCMD60_DNLD_STARTADDR, MMC_APP_CMD60, vcmd60_dnld_start_address);
#endif
#endif
        /// # wait mfg exeution done
        errmsage = THE_CMD13_WATING_MFG_ERR;
        ZYP_Stirng_MMC_CHECK_CMD(zyp_mmc_send_status(card, cmd13_repsonce0), err, tag_virgin, "cmd13 err");
        /// ZYP_DEBUG_MMC cmd13_repsonce0

#if IS_ENBALE_FactoryModeProcess
        zyp_construct_vriginal_process_message_fream_to_send(&factory_mode_process_t, THE_CMD13_WATING_MFG, MMC_SEND_STATUS, MMC_PARME_ZEARO);
#endif
        /// #Configure the ffu mode   9060 here err  too big HOST_USER_LBA or TRUE_OP_RATIO
        errmsage = THE_CMD6_FFU_MODE_ERR;
        ZYP_Stirng_MMC_CHECK_CMD(zyp_switch_cmd(card, cmd6_parm_ffu_mode), err, tag_virgin, "cmd6_parm_ffu_mode err");
#if IS_ENBALE_FactoryModeProcess
        zyp_construct_vriginal_process_message_fream_to_send(&factory_mode_process_t, THE_CMD6_FFU_MODE, MMC_SWITCH, cmd6_parm_ffu_mode);
#endif

        vTaskDelay(pdMS_TO_TICKS(500));
#if 0
        for (int i = 0; i < 5000; i++)
        {
            sdmmc_command_t cmd = {
                .opcode = MMC_SEND_STATUS,
                .arg = MMC_ARG_RCA(card->rca),
                .flags = SCF_CMD_AC | SCF_RSP_R1};
            esp_err_t err = sdmmc_send_cmd(card, &cmd);
            if (cmd.response[0] == MMC_TRANSFER_STATE)
            {
                ZYP_DEBUG_MMC(" MMC_TRANSFER_STATE\n");
                break;
            }
            if (i%500==0)
            {
                ZYP_DEBUG_MMC("%d\n",i);
            }
        }
#endif
        errmsage = THE_WRITE_LLF_ADDR_ERR;
#if VIGINAL_MODE_HARD_STARTBIT_NO_FILE_SIZE
        if (virigin_file_size_t.dnld_file_size != 0)
        {
            ZYP_DEBUG("virigin_file_size_t.dnld_file_size %d\n", virigin_file_size_t.dnld_file_size);
            sdmmc_host_set_card_clk(card->host.slot, SDMMC_FREQ_52M);
            ZYP_Stirng_MMC_CHECK_CMD(zyp_write_psram_to_emmc(card, dnld_addr, virigin_file_size_t.dnld_file_size, cmd25_parm), err, tag_virgin, "dnld_addr err");
        }
#endif
#if !VIGINAL_MODE_HARD_STARTBIT_NO_FILE_SIZE
        ZYP_Stirng_MMC_CHECK_CMD(zyp_write_psram_to_emmc(card, dnld_addr, DNLD_FILE_SIZE, cmd25_parm), err, tag_virgin, "llf_addr err");
#endif
        // ZYP_SDMMC_CHECK_CMD(zyp_write_psram_to_emmc(card,llf_addr,DNLD_FILE_SIZE,cmd25_parm),err,tag_virgin,"llf_addr err %s",esp_err_to_name(err));
        // vTaskDelay(pdMS_TO_TICKS(500));
#if IS_ENBALE_FactoryModeProcess
        zyp_construct_vriginal_process_message_fream_to_send(&factory_mode_process_t, THE_WRITE_LLF_ADDR, MMC_WRITE_BLOCK_MULTIPLE, cmd25_parm);
#endif

        ZYP_DEBUG("slot_config.d0 %d\n", gpio_get_level(slot_config.d0));
        /// #FFU install
        errmsage = THE_CMD6_FFU_INSTALL_ERR;
        ZYP_Stirng_MMC_CHECK_CMD(zyp_switch_cmd(card, cmd6_parm_install), err, tag_virgin, "cmd6_parm_FFU_install err");
#if IS_ENBALE_FactoryModeProcess
        zyp_construct_vriginal_process_message_fream_to_send(&factory_mode_process_t, THE_CMD6_FFU_INSTALL, MMC_SWITCH, cmd6_parm_install);
#endif
        /// #config ffu mode
        errmsage = THE_CMD6_CONFIG_PARM_FFU_MODE_ERR;
        ZYP_Stirng_MMC_CHECK_CMD(zyp_switch_cmd(card, cmd6_parm_ffu_mode), err, tag_virgin, "config cmd6_parm_ffu_mode err");
#if IS_ENBALE_FactoryModeProcess
        zyp_construct_vriginal_process_message_fream_to_send(&factory_mode_process_t, THE_CMD6_CONFIG_PARM_FFU_MODE, MMC_SWITCH, cmd6_parm_ffu_mode);
#endif
        /// # send mainfw bin
        errmsage = THE_WRITE_MAIN_ADDR_ERR;
#if VIGINAL_MODE_HARD_STARTBIT_NO_FILE_SIZE
        if (virigin_file_size_t.main_file_size != 0)
        {
            ZYP_DEBUG("virigin_file_size_t.main_file_size %d\n", virigin_file_size_t.main_file_size);
            ZYP_Stirng_MMC_CHECK_CMD(zyp_write_psram_to_emmc(card, main_addr, virigin_file_size_t.main_file_size, cmd25_parm), err, tag_virgin, "main_addr err");
        }
#endif
#if !VIGINAL_MODE_HARD_STARTBIT_NO_FILE_SIZE
        ZYP_Stirng_MMC_CHECK_CMD(zyp_write_psram_to_emmc(card, main_addr, MAIN_FILE_SIZE, cmd25_parm), err, tag_virgin, "main_addr err");
#endif
        // ZYP_SDMMC_CHECK_CMD(zyp_write_psram_to_emmc(card,main_addr,MAIN_FILE_SIZE,cmd25_parm),err,tag_virgin,"main_addr err %s",esp_err_to_name(err));
        // vTaskDelay(pdMS_TO_TICKS(500));
        ZYP_Stirng_MMC_CHECK_CMD(zyp_mmc_send_status(card, cmd13_repsonce0), err, tag_virgin, "cmd13 err");
#if IS_ENBALE_FactoryModeProcess
        zyp_construct_vriginal_process_message_fream_to_send(&factory_mode_process_t, THE_WRITE_MAIN_ADDR, MMC_WRITE_BLOCK_MULTIPLE, cmd25_parm);
#endif
        /// #FFU install
        errmsage = THE_LAST_CMD6_PARM_INSTALL_ERR;
        ZYP_Stirng_MMC_CHECK_CMD(zyp_switch_cmd(card, cmd6_parm_install), err, tag_virgin, "last cmd6_parm_install err");
        ZYP_DEBUG_MMC("------------zyp_virgin_flow end-------\n");
#if IS_ENBALE_FactoryModeProcess
        zyp_construct_vriginal_process_message_fream_to_send(&factory_mode_process_t, THE_LAST_CMD6_PARM_INSTALL, MMC_SWITCH, cmd6_parm_install);
#endif
        errmsage = THE_VIRGIN_FLOW_SUCCESS;
#endif

#if NOT_ENABLE_FORMAT_STRING_TYPE
#if ENABLE_CMD60_CMD61
        /// #enable device enter card initial mode and continue running in rom mode(avoid to run into main fw)

        ZYP_SDMMC_CHECK_CMD(zyp_send_cmd60_cmd61_random(card, cmd61_param, MMC_APP_CMD61), err, tag_virgin, "one cmd61 err");
        ZYP_SDMMC_CHECK_CMD(zyp_send_cmd60_cmd61_random(card, cmd61_param, MMC_APP_CMD61), err, tag_virgin, "twice cmd61 err");
#endif
        ////#enter transfer mode
        ZYP_SDMMC_CHECK_CMD(zyp_cmd0_go_idle_state(card), err, tag_virgin, "cmd0 err");
        ZYP_DEBUG_MMC("card->is_mmc :%d\n", card->is_mmc);
        card->is_mmc = 1; /// must keep or cmd3 send twice err?  cmd3 hava jujy  card->is_mmc
        ZYP_SDMMC_CHECK_CMD(zyp_mmc_send_cmd_send_op_cond(card), err, tag_virgin, "cmd1 err");
        ZYP_SDMMC_CHECK_CMD(zyp_sdmmc_init_cid(card), err, tag_virgin, "cmd2 err");
        ZYP_SDMMC_CHECK_CMD(zyp_sdmmc_send_cmd_set_relative_addr(card, &card->rca), err, tag_virgin, "cmd3 err");

        ZYP_SDMMC_CHECK_CMD(zyp_sdmmc_send_cmd_send_csd(card, &card->csd), err, tag_virgin, "cmd9 err");

        ZYP_DEBUG_MMC("CMD9 after card->rca :%d\n", card->rca);
        card->rca = 1;
        ZYP_SDMMC_CHECK_CMD(zyp_mmc_send_cmd_select_card(card, card->rca), err, TAG, "cmd7 err");

        /// #check register
        ZYP_SDMMC_CHECK_CMD(sdmmc_init_mmc_read_ext_csd(card), err, tag_virgin, "cmd8 err: %x", err);

        /// Switch frequeny to 8bit 50M
#if IS_ENABLE_8BIT_50M
        ZYP_SDMMC_CHECK_CMD(zyp_switch_cmd(card, cmd6_set_bus_8bit_sdr), err, tag_virgin, "cmd6_set_bus_8bit_sdr err");
        ZYP_SDMMC_CHECK_CMD(zyp_switch_cmd(card, cmd6_set_high_speed), err, tag_virgin, "cmd6_set_high_speed err");
#endif

#if ENABLE_CMD60_CMD61
        /// indicates that this is a write sector data cmd with still a subsequent cmd60
        ZYP_SDMMC_CHECK_CMD(zyp_send_cmd60_cmd61_random(card, cmd60_parm1, MMC_APP_CMD60), err, tag_virgin, "cmd60_parm1 err");
        /// indicates that these data will be written begin at ram address 0b04000(data buffer area in sram)
        ZYP_SDMMC_CHECK_CMD(zyp_send_cmd60_cmd61_random(card, cmd60_parm2, MMC_APP_CMD60), err, tag_virgin, "cmd60_parm2 err");
#endif

        /// write data to the specified address above, with cmd12 to end
        ZYP_SDMMC_CHECK_CMD(zyp_write_psram_to_emmc(card, llf_addr, LLF_FILE_SIZE, cmd25_parm), err, tag_virgin, "write_llf err %s", esp_err_to_name(err));

#if ENABLE_CMD60_CMD61
        /// # set execute mode to VCMD60_DEPLOY_AND_EXEC
        ZYP_SDMMC_CHECK_CMD(zyp_send_cmd60_cmd61_random(card, vcmd60_deploy_exec, MMC_APP_CMD60), err, tag_virgin, "vcmd60_deploy_exec err");

        /// # set dnld binary source address
        ZYP_SDMMC_CHECK_CMD(zyp_send_cmd60_cmd61_random(card, vcmd60_dnld_addr, MMC_APP_CMD60), err, tag_virgin, "vcmd60_dnld_addr err");

        /// # copy dnld from dbuf and jump to dnld start address
        ZYP_SDMMC_CHECK_CMD(zyp_send_cmd60_cmd61_random(card, vcmd60_dnld_start_address, MMC_APP_CMD60), err, tag_virgin, "vcmd60_dnld_start_address err");
#endif
        /// # wait mfg exeution done
        ZYP_SDMMC_CHECK_CMD(zyp_mmc_send_status(card, cmd13_repsonce0), err, tag_virgin, "cmd8 err");
        /// ZYP_DEBUG_MMC cmd13_repsonce0
        vTaskDelay(pdMS_TO_TICKS(500));

        /// #Configure the ffu mode   9060 here err  too big HOST_USER_LBA or TRUE_OP_RATIO
        ZYP_SDMMC_CHECK_CMD(zyp_switch_cmd(card, cmd6_parm_ffu_mode), err, tag_virgin, "cmd6_parm_ffu_mode err");
        ZYP_SDMMC_CHECK_CMD(zyp_write_psram_to_emmc(card, llf_addr, DNLD_FILE_SIZE, cmd25_parm), err, tag_virgin, "llf_addr err");
        vTaskDelay(pdMS_TO_TICKS(1000));

        /// #FFU install
        ZYP_SDMMC_CHECK_CMD(zyp_switch_cmd(card, cmd6_parm_install), err, tag_virgin, "cmd6_parm_install err");

        /// #config ffu mode
        ZYP_SDMMC_CHECK_CMD(zyp_switch_cmd(card, cmd6_parm_ffu_mode), err, tag_virgin, "config cmd6_parm_ffu_mode err");

        /// # send mainfw bin
        ZYP_SDMMC_CHECK_CMD(zyp_write_psram_to_emmc(card, main_addr, MAIN_FILE_SIZE, cmd25_parm), err, tag_virgin, "main_addr err");
        vTaskDelay(pdMS_TO_TICKS(1000));

        /// #FFU install
        ZYP_SDMMC_CHECK_CMD(zyp_switch_cmd(card, cmd6_parm_install), err, tag_virgin, "last cmd6_parm_install err");
        ZYP_DEBUG_MMC("------------zyp_virgin_flow end-------\n");
#endif

#if 0
    // 1. CMD61: Enter card initial mode (ROM mode)
    // ZYP_DEBUG_MMC("zyp_send_cmd60_cmd61_random  1\n");
    // err = zyp_send_cmd60_cmd61_random(card,cmd61_param,MMC_APP_CMD61);
    // if (err != ESP_OK) {
    //     ZYP_DEBUG_MMC("CMD61 failed:");
    //     return err;
    // }

    // ZYP_DEBUG_MMC("zyp_send_cmd60_cmd61_random  2\n");
    // err = zyp_send_cmd60_cmd61_random(card,cmd61_param,MMC_APP_CMD61);
    // if (err != ESP_OK) {
    //     ZYP_DEBUG_MMC("CMD61 failed:");
    //     return err;
    // }

    // 2. CMD0: GO_IDLE_STATE
     ZYP_DEBUG_MMC("zyp_cmd0_go_idle_state \n");
    err = zyp_cmd0_go_idle_state(card);
    if (err != ESP_OK) {
        ZYP_DEBUG_MMC("CMD0 failed:");
        return err;
    }

     ZYP_DEBUG_MMC("zyp_mmc_send_cmd_send_op_cond \n");
    // 3. CMD1: SEND_OP_COND
    err = zyp_mmc_send_cmd_send_op_cond(card);
    if (err != ESP_OK) {
         ZYP_DEBUG_MMC("CMD1 failed:");
        return err;
    }

    ZYP_DEBUG_MMC("zyp_sdmmc_init_cid \n");
    // 4. CMD2: ALL_SEND_CID
    err = zyp_sdmmc_init_cid(card);
    if (err != ESP_OK) {
        ZYP_DEBUG_MMC("CMD2 failed:");
        return err;
    }

    ZYP_DEBUG_MMC("zyp_sdmmc_send_cmd_set_relative_addr \n");
    // 5. CMD3: SET_RELATIVE_ADDR
    err = zyp_sdmmc_send_cmd_set_relative_addr(card, &card->rca);
    if (err != ESP_OK) {
        ZYP_DEBUG_MMC("CMD3 failed:");
        return err;
    }

     ZYP_DEBUG_MMC("zyp_sdmmc_send_cmd_send_csd \n");
    // 6. CMD9: SEND_CSD
    err = zyp_sdmmc_send_cmd_send_csd(card, &card->csd);
    if (err != ESP_OK) {
         ZYP_DEBUG_MMC("CMD9 failed:");
        return err;
    }


    // // 7. CMD6: Switch to 8-bit SDR
    // err = zyp_switch_cmd(card, 0x03B70200);
    // if (err != ESP_OK) {
    //     ESP_LOGE(tag_virgin, "CMD6 (8-bit SDR) failed: %s", esp_err_to_name(err));
    //     return err;
    // }

    // // 8. CMD6: Set high speed
    // err = zyp_switch_cmd(card, 0x03B90100);
    // if (err != ESP_OK) {
    //     ESP_LOGE(tag_virgin, "CMD6 (High Speed) failed: %s", esp_err_to_name(err));
    //     return err;
    // }


    // 9. CMD60: Set VCMD60 Deploy & Execute mode
    err = zyp_send_cmd60_cmd61_random(card,cmd60_parm1,MMC_APP_CMD60);
    if (err != ESP_OK) {
        ZYP_DEBUG_MMC("CMD60 failed:");
        return err;
    }

    // 10. CMD60: Set Download Address
    err = zyp_send_cmd60_cmd61_random(card,cmd60_parm2,MMC_APP_CMD60);
    if (err != ESP_OK) {
         ZYP_DEBUG_MMC("CMD60 failed:");
        return err;
    }

        
     err=zyp_write_psram_to_emmc(card,llf_addr,LLF_FILE_SIZE,cmd25_parm);
     if (err != ESP_OK) {
         ZYP_DEBUG_MMC("llf_addr failed:");
        return err;
     }
     
      err=zyp_send_cmd60_cmd61_random(card,vcmd60_deploy_exec,MMC_APP_CMD60);
       if (err != ESP_OK) {
        ZYP_DEBUG_MMC("vcmd60_deploy_exec failed:");
        return err;
     }  

     err=zyp_send_cmd60_cmd61_random(card,vcmd60_dnld_addr,MMC_APP_CMD60);
       if (err != ESP_OK) {
       ZYP_DEBUG_MMC("vcmd60_dnld_addr failed:");
        return err;
     }  

     err=zyp_send_cmd60_cmd61_random(card,vcmd60_dnld_start_address,MMC_APP_CMD60);
     if (err != ESP_OK) {
         ZYP_DEBUG_MMC("vcmd60_dnld_start_address failed:");
        return err;
     }  

    err=zyp_mmc_send_status(card,cmd13_repsonce0);
     if (err != ESP_OK) {
        ZYP_DEBUG_MMC("zyp_mmc_send_status failed:");
        return err;
     }  

    err=zyp_switch_cmd(card,cmd6_parm_ffu_mode);
     if (err != ESP_OK) {
        ZYP_DEBUG_MMC("cmd6_parm_ffu_mode failed:");
        return err;
     } 

    err=zyp_write_psram_to_emmc(card,llf_addr,DNLD_FILE_SIZE,cmd25_parm);
    if (err != ESP_OK) {
       ZYP_DEBUG_MMC("llf_addr failed:");
        return err;
     } 


    err=zyp_switch_cmd(card,cmd6_parm_install);
        if (err != ESP_OK) {
        ESP_LOGE(tag_virgin, "CMD60 (Download Address) failed: %s", esp_err_to_name(err));
        return err;
     } 


    err=zyp_switch_cmd(card,cmd6_parm_ffu_mode);
    if (err != ESP_OK) {
        ESP_LOGE(tag_virgin, "CMD60 (Download Address) failed: %s", esp_err_to_name(err));
        return err;
     } 

    err=zyp_write_psram_to_emmc(card,main_addr,MAIN_FILE_SIZE,cmd25_parm);
     if (err != ESP_OK) {
        ESP_LOGE(tag_virgin, "CMD60 (Download Address) failed: %s", esp_err_to_name(err));
        return err;
     } 


      err=zyp_switch_cmd(card,cmd6_parm_install);
      if (err != ESP_OK) {
        ESP_LOGE(tag_virgin, "CMD60 (Download Address) failed: %s", esp_err_to_name(err));
        return err;
     }
#endif
    }

    return ESP_OK;
}
